# Quickstart URL: https://www.prisma.io/docs/getting-started/quickstart-prismaPostgres In this Quickstart guide, you'll learn how to get started from scratch with Prisma ORM and a **Prisma Postgres** database in a plain **TypeScript** project. It covers the following workflows: - Creating a [Prisma Postgres](https://www.prisma.io/postgres?utm_source=docs) database - Schema migrations and queries (via [Prisma ORM](https://www.prisma.io/orm)) - Connection pooling and caching (via [Prisma Accelerate](https://www.prisma.io/accelerate)) ## Prerequisites To successfully complete this tutorial, you need: - a [Prisma Data Platform](https://console.prisma.io/) (PDP) account - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) ## 1. Set up a Prisma Postgres database in the Platform Console Follow these steps to create your Prisma Postgres database: 1. Log in to [Prisma Data Platform](https://console.prisma.io/) and open the Console. 1. In a [workspace](/platform/about#workspace) of your choice, click the **New project** button. 1. Type a name for your project in the **Name** field, e.g. **hello-ppg**. 1. In the **Prisma Postgres** section, click the **Get started** button. 1. In the **Region** dropdown, select the region that's closest to your current location, e.g. **US East (N. Virginia)**. 1. Click the **Create project** button. At this point, you'll be redirected to the **Database** page where you will need to wait for a few seconds while the status of your database changes from **`PROVISIONING`** to **`CONNECTED`**. Once the green **`CONNECTED`** label appears, your database is ready to use! ## 2. Download example and install dependencies Copy the `try-prisma` command that's shown in the Console, paste it into your terminal and execute it. For reference, this is what the command looks like: ```terminal npx try-prisma@latest \ --template databases/prisma-postgres \ --name hello-prisma \ --install npm ``` Once the `try-prisma` command has terminated, navigate into the project directory: ```terminal cd hello-prisma ``` ## 3. Set database connection URL The connection to your database is configured via an environment variable in a `.env` file. First, rename the existing `.env.example` file to just `.env`: ```terminal mv .env.example .env ``` Then, in your project environment in the Platform console, find your database credentials in the **Set up database access** section, copy the `DATABASE_URL` environment variable and paste them into the `.env` file. For reference, the file should now look similar to this: ```bash no-copy DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=ey...." ``` ## 4. Create database tables (with a schema migration) Next, you need to create the tables in your database. You can do this by creating and executing a schema migration with the following command of the Prisma CLI: ```terminal npx prisma migrate dev --name init ``` This will map the `User` and `Post` models that are defined in your [Prisma schema](/orm/prisma-schema/) to your database. You can also review the SQL migration that was executed and created the tables in the newly created `prisma/migrations` directory. ## 5. Execute queries with Prisma ORM The [`src/queries.ts`](https://github.com/prisma/prisma-examples/blob/latest/databases/prisma-postgres/src/queries.ts) script contains a number of CRUD queries that will write and read data in your database. You can execute it by running the following command in your terminal: ```terminal npm run queries ``` Once the script has completed, you can inspect the logs in your terminal or use Prisma Studio to explore what records have been created in the database: ```terminal npx prisma studio ``` ## 6. Explore caching with Prisma Accelerate The [`src/caching.ts`](https://github.com/prisma/prisma-examples/blob/latest/databases/prisma-postgres/src/caching.ts) script contains a sample query that uses [Stale-While-Revalidate](/accelerate/caching#stale-while-revalidate-swr) (SWR) and [Time-To-Live](/accelerate/caching#time-to-live-ttl) (TTL) to cache a database query using Prisma Accelerate. You can execute it as follows: ```terminal npm run caching ``` Take note of the time that it took to execute the query, e.g.: ```no-copy The query took 2009.2467149999998ms. ``` Now, run the script again: ```terminal npm run caching ``` You'll notice that the time the query took will be a lot shorter this time, e.g.: ```no-copy The query took 300.5655280000001ms. ``` ## 7. Next steps In this Quickstart guide, you have learned how to get started with Prisma ORM in a plain TypeScript project. Feel free to explore the Prisma Client API a bit more on your own, e.g. by including filtering, sorting, and pagination options in the `findMany` query or exploring more operations like `update` and `delete` queries. ### Explore the data in Prisma Studio Prisma ORM comes with a built-in GUI to view and edit the data in your database. You can open it using the following command: ```terminal npx prisma studio ``` With Prisma Postgres, you can also directly use Prisma Studio inside the [Console](https://console.prisma.io) by selecting the **Studio** tab in your project. ### Build a fullstack app with Next.js Learn how to use Prisma Postgres in a fullstack app: - [Build a fullstack app with Next.js 15](/guides/nextjs) - [Next.js 15 example app](https://github.com/prisma/nextjs-prisma-postgres-demo) (including authentication) ### Explore ready-to-run Prisma ORM examples Check out the [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository on GitHub to see how Prisma ORM can be used with your favorite library. The repo contains examples with Express, NestJS, GraphQL as well as fullstack examples with Next.js and Vue.js, and a lot more. These examples use SQLite by default but you can follow the instructions in the project README to switch to Prisma Postgres in a few simple steps. --- # Quickstart URL: https://www.prisma.io/docs/getting-started/quickstart-sqlite In this Quickstart guide, you'll learn how to get started with Prisma ORM from scratch using a plain **TypeScript** project and a local **SQLite** database file. It covers **data modeling**, **migrations** and **querying** a database. If you want to use Prisma ORM with your own PostgreSQL, MySQL, MongoDB or any other supported database, go here instead: - [Start with Prisma ORM from scratch](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql) - [Add Prisma ORM to an existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql) ## Prerequisites You need [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions). ## 1. Create TypeScript project and set up Prisma ORM As a first step, create a project directory and navigate into it: ```terminal mkdir hello-prisma cd hello-prisma ``` Next, initialize a TypeScript project using npm: ```terminal npm init -y npm install typescript tsx @types/node --save-dev ``` This creates a `package.json` with an initial setup for your TypeScript app. :::info See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. ::: Now, initialize TypeScript: ```terminal npx tsc --init ``` Then, install the Prisma CLI as a development dependency in the project: ```terminal npm install prisma --save-dev ``` Finally, set up Prisma ORM with the `init` command of the Prisma CLI: ```terminal npx prisma init --datasource-provider sqlite --output ../generated/prisma ``` This creates a new `prisma` directory with a `schema.prisma` file and configures SQLite as your database. You're now ready to model your data and create your database with some tables. :::note For best results, make sure that you add a line to your `.gitignore` in order to exclude the generated client from your application. In this example, we want to exclude the `generated/prisma` directory. ```code file=.gitignore //add-start generated/prisma/ //add-end ``` ::: ## 2. Model your data in the Prisma schema The Prisma schema provides an intuitive way to model data. Add the following models to your `schema.prisma` file: ```prisma file=prisma/schema.prisma showLineNumbers model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int } ``` Models in the Prisma schema have two main purposes: - Represent the tables in the underlying database - Serve as foundation for the generated Prisma Client API In the next section, you will map these models to database tables using Prisma Migrate. ## 3. Run a migration to create your database tables with Prisma Migrate At this point, you have a Prisma schema but no database yet. Run the following command in your terminal to create the SQLite database and the `User` and `Post` tables represented by your models: ```terminal npx prisma migrate dev --name init ``` This command did three things: 1. It created a new SQL migration file for this migration in the `prisma/migrations` directory. 2. It executed the SQL migration file against the database. 3. It ran `prisma generate` under the hood (which installed the `@prisma/client` package and generated a tailored Prisma Client API based on your models). Because the SQLite database file didn't exist before, the command also created it inside the `prisma` directory with the name `dev.db` as defined via the environment variable in the `.env` file. Congratulations, you now have your database and tables ready. Let's go and learn how you can send some queries to read and write data! ## 4. Explore how to send queries to your database with Prisma Client To get started with Prisma Client, you need to install the `@prisma/client` package: ```terminal copy npm install @prisma/client ``` The install command invokes `prisma generate` for you which reads your Prisma schema and generates a version of Prisma Client that is _tailored_ to your models. To send queries to the database, you will need a TypeScript file to execute your Prisma Client queries. Create a new file called `script.ts` for this purpose: ```terminal touch script.ts ``` Then, paste the following boilerplate into it: ```ts file=script.ts showLineNumbers import { PrismaClient } from '../generated/prisma' const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` This code contains a `main` function that's invoked at the end of the script. It also instantiates `PrismaClient` which represents the query interface to your database. ### 4.1. Create a new `User` record Let's start with a small query to create a new `User` record in the database and log the resulting object to the console. Add the following code to your `script.ts` file: ```ts file=script.ts highlight=6-12;add showLineNumbers import { PrismaClient } from '../generated/prisma' const prisma = new PrismaClient() async function main() { // add-start const user = await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', }, }) console.log(user) // add-end } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Instead of copying the code, you can type it out in your editor to experience the autocompletion Prisma Client provides. You can also actively invoke the autocompletion by pressing the CTRL+SPACE keys on your keyboard. Next, execute the script with the following command: ```terminal npx tsx script.ts ``` ```code no-copy { id: 1, email: 'alice@prisma.io', name: 'Alice' } ``` Great job, you just created your first database record with Prisma Client! 🎉 In the next section, you'll learn how to read data from the database. ### 4.2. Retrieve all `User` records Prisma Client offers various queries to read data from your database. In this section, you'll use the `findMany` query that returns _all_ the records in the database for a given model. Delete the previous Prisma Client query and add the new `findMany` query instead: ```ts file=script.ts highlight=6-7;add showLineNumbers import { PrismaClient } from '../generated/prisma' const prisma = new PrismaClient() async function main() { // add-start const users = await prisma.user.findMany() console.log(users) // add-end } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Execute the script again: ```terminal npx tsx script.ts ``` ```code no-copy [{ id: 1, email: 'alice@prisma.io', name: 'Alice' }] ``` Notice how the single `User` object is now enclosed with square brackets in the console. That's because the `findMany` returned an array with a single object inside. ### 4.3. Explore relation queries with Prisma Client One of the main features of Prisma Client is the ease of working with [relations](/orm/prisma-schema/data-model/relations). In this section, you'll learn how to create a `User` and a `Post` record in a nested write query. Afterwards, you'll see how you can retrieve the relation from the database using the `include` option. First, adjust your script to include the nested query: ```ts file=script.ts highlight=6-24;add showLineNumbers import { PrismaClient } from '../generated/prisma' const prisma = new PrismaClient() async function main() { // add-start const user = await prisma.user.create({ data: { name: 'Bob', email: 'bob@prisma.io', posts: { create: [ { title: 'Hello World', published: true }, { title: 'My second post', content: 'This is still a draft' } ], }, }, }) console.log(user) // add-end } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Run the query by executing the script again: ```terminal npx tsx script.ts ``` ```code no-copy { id: 2, email: 'bob@prisma.io', name: 'Bob' } ``` By default, Prisma Client only returns _scalar_ fields in the result objects of a query. That's why, even though you also created a new `Post` record for the new `User` record, the console only printed an object with three scalar fields: `id`, `email` and `name`. In order to also retrieve the `Post` records that belong to a `User`, you can use the `include` option via the `posts` relation field: ```ts file=script.ts highlight=6-11;add showLineNumbers import { PrismaClient } from '../generated/prisma' const prisma = new PrismaClient() async function main() { // add-start const usersWithPosts = await prisma.user.findMany({ include: { posts: true, }, }) console.dir(usersWithPosts, { depth: null }) // add-end } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Run the script again to see the results of the nested read query: ```terminal npx tsx script.ts ``` ```code no-copy [ { id: 1, email: 'alice@prisma.io', name: 'Alice', posts: [] }, { id: 2, email: 'bob@prisma.io', name: 'Bob', posts: [ { id: 1, title: 'Hello World', content: null, published: true, authorId: 2 }, { id: 2, title: 'My second post', content: 'This is still a draft', published: false, authorId: 2 } ] } ] ``` This time, you're seeing two `User` objects being printed. Both of them have a `posts` field (which is empty for `"Alice"` and populated with two `Post` objects for `"Bob"`) that represents the `Post` records associated with them. Notice that the objects in the `usersWithPosts` array are fully typed as well. This means you will get autocompletion and the TypeScript compiler will prevent you from accidentally typing them. ## 5. Next steps In this Quickstart guide, you have learned how to get started with Prisma ORM in a plain TypeScript project. Feel free to explore the Prisma Client API a bit more on your own, e.g. by including filtering, sorting, and pagination options in the `findMany` query or exploring more operations like `update` and `delete` queries. ### Explore the data in Prisma Studio Prisma ORM comes with a built-in GUI to view and edit the data in your database. You can open it using the following command: ```terminal npx prisma studio ``` ### Set up Prisma ORM with your own database If you want to move forward with Prisma ORM using your own PostgreSQL, MySQL, MongoDB or any other supported database, follow the Set Up Prisma ORM guides: - [Start with Prisma ORM from scratch](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql) - [Add Prisma ORM to an existing project](/getting-started/setup-prisma/add-to-existing-project) ### Get query insights and analytics with Prisma Optimize [Prisma Optimize](/optimize) helps you generate insights and provides recommendations that can help you make your database queries faster. Optimize aims to help developers of all skill levels write efficient database queries, reducing database load and making applications more responsive. ### Explore ready-to-run Prisma ORM examples Check out the [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository on GitHub to see how Prisma ORM can be used with your favorite library. The repo contains examples with Express, NestJS, GraphQL as well as fullstack examples with Next.js and Vue.js, and a lot more. ### Speed up your database queries with Prisma Accelerate [Prisma Accelerate](/accelerate) is a connection pooler and global database cache that can drastically speed up your database queries. Check out the [Speed Test](https://accelerate-speed-test.prisma.io/) or try Accelerate with your favorite framework: | Demo | Description | | ----------------------------------------------- | -------------------------------------------------------------------------- | | [`nextjs-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/nextjs-starter) | A Next.js project using Prisma Accelerate's caching and connection pooling | | [`svelte-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/svelte-starter) | A SvelteKit project using Prisma Accelerate's caching and connection pooling | | [`solidstart-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/solidstart-starter) | A Solidstart project using Prisma Accelerate's caching and connection pooling | | [`remix-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/remix-starter) | A Remix project using Prisma Accelerate's caching and connection pooling | | [`nuxt-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/nuxtjs-starter) | A Nuxt.js project using Prisma Accelerate's caching and connection pooling | | [`astro-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/astro-starter) | An Astro project using Prisma Accelerate's caching and connection pooling | ### Build an app with Prisma ORM The Prisma blog features comprehensive tutorials about Prisma ORM, check out our latest ones: - [Build a fullstack app with Next.js](https://www.youtube.com/watch?v=QXxy8Uv1LnQ&ab_channel=ByteGrad) - [Build a fullstack app with Remix](https://www.prisma.io/blog/fullstack-remix-prisma-mongodb-1-7D0BfTXBmB6r) (5 parts, including videos) - [Build a REST API with NestJS](https://www.prisma.io/blog/nestjs-prisma-rest-api-7D056s1BmOL0) --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-cockroachdb To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` The `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`. You now need to adjust the connection URL to point to your own database. The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. CockroachDB uses the PostgreSQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines postgresql://USER:PASSWORD@HOST:PORT/DATABASE?PARAMETERS ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `PORT`: The port where your database server is running. The default for CockroachDB is `26257`. - `DATABASE`: The name of the database - `PARAMETERS`: Any additional connection parameters. See the CockroachDB documentation [here](https://www.cockroachlabs.com/docs/stable/connection-parameters.html#additional-connection-parameters). For a [CockroachDB Serverless](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart.html) or [Cockroach Dedicated](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart-trial-cluster) database hosted on [CockroachDB Cloud](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart/), the [connection URL](/orm/reference/connection-urls) looks similar to this: ```bash file=.env DATABASE_URL="postgresql://:@..cockroachlabs.cloud:26257/defaultdb?sslmode=verify-full&sslrootcert=$HOME/.postgresql/root.crt&options=--" ``` To find your connection string on CockroachDB Cloud, click the 'Connect' button on the overview page for your database cluster, and select the 'Connection string' tab. For a [CockroachDB database hosted locally](https://www.cockroachlabs.com/docs/stable/secure-a-cluster.html), the [connection URL](/orm/reference/connection-urls) looks similar to this: ```bash file=.env DATABASE_URL="postgresql://root@localhost:26257?sslmode=disable" ``` Your connection string is displayed as part of the welcome text when starting CockroachDB from the command line. --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-mysql To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: ```bash file=.env DATABASE_URL="mysql://johndoe:randompassword@localhost:3306/mydb" ``` We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. You now need to adjust the connection URL to point to your own database. The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. For MySQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines mysql://USER:PASSWORD@HOST:PORT/DATABASE ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `PORT`: The port where your database server is running (typically `3306` for MySQL) - `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) As an example, for a MySQL database hosted on AWS RDS, the [connection URL](/orm/reference/connection-urls) might look similar to this: ```bash file=.env DATABASE_URL="mysql://johndoe:XXX@mysql–instance1.123456789012.us-east-1.rds.amazonaws.com:3306/mydb" ``` When running MySQL locally, your connection URL typically looks similar to this: ```bash file=.env DATABASE_URL="mysql://root:randompassword@localhost:3306/mydb" ``` --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-planetscale To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` You will also need to set the relation mode type to `prisma` in order to [emulate foreign key constraints](/orm/overview/databases/planetscale#option-1-emulate-relations-in-prisma-client) in the `datasource` block: ```prisma file=schema.prisma highlight=4;add showLineNumbers datasource db { provider = "mysql" url = env("DATABASE_URL") //add-next-line relationMode = "prisma" } ``` > **Note**: Since February 2024, you can alternatively [use foreign key constraints on a database-level in PlanetScale](/orm/overview/databases/planetscale#option-2-enable-foreign-key-constraints-in-the-planetscale-database-settings), which omits the need for setting `relationMode = "prisma"`. The `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: ```bash file=.env DATABASE_URL="mysql://janedoe:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" ``` You now need to adjust the connection URL to point to your own database. The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. PlanetScale uses the MySQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines mysql://USER:PASSWORD@HOST:PORT/DATABASE ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `PORT`: The port where your database server is running (typically `3306` for MySQL) - `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) For a database hosted with PlanetScale, the [connection URL](/orm/reference/connection-urls) looks similar to this: ```bash file=.env DATABASE_URL="mysql://myusername:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" ``` The connection URL for a given database branch can be found from your PlanetScale account by going to the overview page for the branch and selecting the 'Connect' dropdown. In the 'Passwords' section, generate a new password and select 'Prisma' to get the Prisma format for the connection URL.
Alternative method: connecting using the PlanetScale CLI Alternatively, you can connect to your PlanetScale database server using the [PlanetScale CLI](https://planetscale.com/docs/concepts/planetscale-environment-setup), and use a local connection URL. In this case the connection URL will look like this: ```bash file=.env DATABASE_URL="mysql://root@localhost:PORT/mydb" ``` We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. To connect to your branch, use the following command: ```terminal pscale connect prisma-test branchname --port PORT ``` The `--port` flag can be omitted if you are using the default port `3306`.
--- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-postgresql To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`: ```bash file=.env DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" ``` We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. You now need to adjust the connection URL to point to your own database. The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For PostgreSQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `HOST`: The name of your host name (for the local environment, it is `localhost`) - `PORT`: The port where your database server is running (typically `5432` for PostgreSQL) - `DATABASE`: The name of the [database](https://www.postgresql.org/docs/12/manage-ag-overview.html) - `SCHEMA`: The name of the [schema](https://www.postgresql.org/docs/12/ddl-schemas.html) inside the database If you're unsure what to provide for the `schema` parameter for a PostgreSQL connection URL, you can probably omit it. In that case, the default schema name `public` will be used. As an example, for a PostgreSQL database hosted on Heroku, the [connection URL](/orm/reference/connection-urls) might look similar to this: ```bash file=.env DATABASE_URL="postgresql://opnmyfngbknppm:XXX@ec2-46-137-91-216.eu-west-1.compute.amazonaws.com:5432/d50rgmkqi2ipus?schema=hello-prisma" ``` When running PostgreSQL locally on macOS, your user and password as well as the database name _typically_ correspond to the current _user_ of your OS, e.g. assuming the user is called `janedoe`: ```bash file=.env DATABASE_URL="postgresql://janedoe:janedoe@localhost:5432/janedoe?schema=hello-prisma" ``` --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-node-sqlserver To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "sqlserver" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: The following example connection URL [uses SQL authentication](/orm/overview/databases/sql-server), but there are [other ways to format your connection URL](/orm/overview/databases/sql-server) ```bash file=.env DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=sa;password=r@ndomP@$$w0rd;trustServerCertificate=true" ``` We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. Adjust the connection URL to match your setup - see [Microsoft SQL Server connection URL](/orm/overview/databases/sql-server) for more information. > Make sure TCP/IP connections are enabled via [SQL Server Configuration Manager](https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-configuration-manager?view=sql-server-ver16&viewFallbackFrom=sql-server-ver16) to avoid `No connection could be made because the target machine actively refused it. (os error 10061)` --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-cockroachdb To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` The `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`. You now need to adjust the connection URL to point to your own database. The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. CockroachDB uses the PostgreSQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines postgresql://USER:PASSWORD@HOST:PORT/DATABASE?PARAMETERS ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `PORT`: The port where your database server is running. The default for CockroachDB is `26257`. - `DATABASE`: The name of the database - `PARAMETERS`: Any additional connection parameters. See the CockroachDB documentation [here](https://www.cockroachlabs.com/docs/stable/connection-parameters.html#additional-connection-parameters). For a [CockroachDB Serverless](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart.html) or [Cockroach Dedicated](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart-trial-cluster) database hosted on [CockroachDB Cloud](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart/), the [connection URL](/orm/reference/connection-urls) looks similar to this: ```bash file=.env DATABASE_URL="postgresql://:@..cockroachlabs.cloud:26257/defaultdb?sslmode=verify-full&sslrootcert=$HOME/.postgresql/root.crt&options=--" ``` To find your connection string on CockroachDB Cloud, click the 'Connect' button on the overview page for your database cluster, and select the 'Connection string' tab. For a [CockroachDB database hosted locally](https://www.cockroachlabs.com/docs/stable/secure-a-cluster.html), the [connection URL](/orm/reference/connection-urls) looks similar to this: ```bash file=.env DATABASE_URL="postgresql://root@localhost:26257?sslmode=disable" ``` Your connection string is displayed as part of the welcome text when starting CockroachDB from the command line. --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-mysql To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "mysql" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: ```bash file=.env DATABASE_URL="mysql://johndoe:randompassword@localhost:3306/mydb" ``` We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. You now need to adjust the connection URL to point to your own database. The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. For MySQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines mysql://USER:PASSWORD@HOST:PORT/DATABASE ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `PORT`: The port where your database server is running (typically `3306` for MySQL) - `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) As an example, for a MySQL database hosted on AWS RDS, the [connection URL](/orm/reference/connection-urls) might look similar to this: ```bash file=.env DATABASE_URL="mysql://johndoe:XXX@mysql–instance1.123456789012.us-east-1.rds.amazonaws.com:3306/mydb" ``` When running MySQL locally, your connection URL typically looks similar to this: ```bash file=.env DATABASE_URL="mysql://root:randompassword@localhost:3306/mydb" ``` --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-planetscale To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` You will also need to set the relation mode type to `prisma` in order to [emulate foreign key constraints](/orm/overview/databases/planetscale#option-1-emulate-relations-in-prisma-client) in the `datasource` block: ```prisma file=schema.prisma highlight=4;add showLineNumbers datasource db { provider = "mysql" url = env("DATABASE_URL") //add-next-line relationMode = "prisma" } ``` > **Note**: Since February 2024, you can alternatively [use foreign key constraints on a database-level in PlanetScale](/orm/overview/databases/planetscale#option-2-enable-foreign-key-constraints-in-the-planetscale-database-settings), which omits the need for setting `relationMode = "prisma"`. The `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: ```bash file=.env DATABASE_URL="mysql://janedoe:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" ``` You now need to adjust the connection URL to point to your own database. The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. PlanetScale uses the MySQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines mysql://USER:PASSWORD@HOST:PORT/DATABASE ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `PORT`: The port where your database server is running (typically `3306` for MySQL) - `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) For a database hosted with PlanetScale, the [connection URL](/orm/reference/connection-urls) looks similar to this: ```bash file=.env DATABASE_URL="mysql://myusername:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" ``` The connection URL for a given database branch can be found from your PlanetScale account by going to the overview page for the branch and selecting the 'Connect' dropdown. In the 'Passwords' section, generate a new password and select 'Prisma' to get the Prisma format for the connection URL.
Alternative method: connecting using the PlanetScale CLI Alternatively, you can connect to your PlanetScale database server using the [PlanetScale CLI](https://planetscale.com/docs/concepts/planetscale-environment-setup), and use a local connection URL. In this case the connection URL will look like this: ```bash file=.env DATABASE_URL="mysql://root@localhost:PORT/mydb" ``` We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. To connect to your branch, use the following command: ```terminal pscale connect prisma-test branchname --port PORT ``` The `--port` flag can be omitted if you are using the default port `3306`.
--- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-postgresql To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`: ```bash file=.env DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" ``` We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. You now need to adjust the connection URL to point to your own database. The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For PostgreSQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `HOST`: The name of your host name (for the local environment, it is `localhost`) - `PORT`: The port where your database server is running (typically `5432` for PostgreSQL) - `DATABASE`: The name of the [database](https://www.postgresql.org/docs/12/manage-ag-overview.html) - `SCHEMA`: The name of the [schema](https://www.postgresql.org/docs/12/ddl-schemas.html) inside the database If you're unsure what to provide for the `schema` parameter for a PostgreSQL connection URL, you can probably omit it. In that case, the default schema name `public` will be used. As an example, for a PostgreSQL database hosted on Heroku, the [connection URL](/orm/reference/connection-urls) might look similar to this: ```bash file=.env DATABASE_URL="postgresql://opnmyfngbknppm:XXX@ec2-46-137-91-216.eu-west-1.compute.amazonaws.com:5432/d50rgmkqi2ipus?schema=hello-prisma" ``` When running PostgreSQL locally on macOS, your user and password as well as the database name _typically_ correspond to the current _user_ of your OS, e.g. assuming the user is called `janedoe`: ```bash file=.env DATABASE_URL="postgresql://janedoe:janedoe@localhost:5432/janedoe?schema=hello-prisma" ``` --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-prismaPostgres ## Set up a Prisma Postgres database in the PDP Console Follow these steps to create your Prisma Postgres database: 1. Log in to [PDP Console](https://console.prisma.io/). 1. In a [workspace](/platform/about#workspace) of your choice, click the **New project** button. 1. Type a name for your project in the **Name** field, e.g. **hello-ppg**. 1. In the **Prisma Postgres** section, click the **Get started** button. 1. In the **Region** dropdown, select the region that's closest to your current location, e.g. **US East (N. Virginia)**. 1. Click the **Create project** button. At this point, you'll be redirected to the **Dashboard** where you will need to wait for a few seconds while the status of your database changes from **`PROVISIONING`**, to **`ACTIVATING`** to **`CONNECTED`**. Once the green **`CONNECTED`** label appears, your database is ready to use. In the Console UI, you'll see a code snippet for a `.env` file with two environment variables defined. ## Set environment variables in your local project Copy the `DATABASE_URL` environment variable from the Console UI and paste it into your `.env` file. Your `.env` file should look similar to this: ```bash file=.env no-copy DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=ey..." ``` By setting the `DATABASE_URL` in the `.env` file, you're ensuring that Prisma ORM can connect to your database. The `DATABASE_URL` is used in the `datasource` block in your Prisma schema: ```prisma file=prisma/schema.prisma datasource db { provider = "postgresql" // highlight-next-line url = env("DATABASE_URL") } ``` That's it! You can now start using the Prisma CLI to interact with your Prisma Postgres database. In the next section, you'll learn how to use the Prisma CLI to create and run migrations against your database to update its schema. --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-sqlserver To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "sqlserver" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: The following example connection URL [uses SQL authentication](/orm/overview/databases/sql-server), but there are [other ways to format your connection URL](/orm/overview/databases/sql-server) ```bash file=.env DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=sa;password=r@ndomP@$$w0rd;trustServerCertificate=true" ``` We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. Adjust the connection URL to match your setup - see [Microsoft SQL Server connection URL](/orm/overview/databases/sql-server) for more information. > Make sure TCP/IP connections are enabled via [SQL Server Configuration Manager](https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-configuration-manager?view=sql-server-ver16&viewFallbackFrom=sql-server-ver16) to avoid `No connection could be made because the target machine actively refused it. (os error 10061)` --- # Using Prisma Migrate URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-cockroachdb ## Creating the database schema In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: ```prisma file=prisma/schema.prisma copy showLineNumbers model Post { id BigInt @id @default(sequence()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId BigInt } model Profile { id BigInt @id @default(sequence()) bio String? user User @relation(fields: [userId], references: [id]) userId BigInt @unique } model User { id BigInt @id @default(sequence()) email String @unique name String? posts Post[] profile Profile? } ``` To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: ```terminal npx prisma migrate dev --name init ``` This command does two things: 1. It creates a new SQL migration file for this migration 1. It runs the SQL migration file against the database :::note `generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. ::: Great, you now created three tables in your database with Prisma Migrate 🚀 --- # Using Prisma Migrate URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-mysql ## Creating the database schema In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: ```prisma file=prisma/schema.prisma copy showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String @db.VarChar(255) content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int } model Profile { id Int @id @default(autoincrement()) bio String? user User @relation(fields: [userId], references: [id]) userId Int @unique } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] profile Profile? } ``` To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: ```terminal npx prisma migrate dev --name init ``` This command does two things: 1. It creates a new SQL migration file for this migration 1. It runs the SQL migration file against the database > **Note**: `generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. Great, you now created three tables in your database with Prisma Migrate 🚀 --- # Using Prisma Migrate URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-planetscale ## Creating the database schema In this guide, you'll use Prisma's [`db push` command](/orm/prisma-migrate/workflows/prototyping-your-schema) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: ```prisma file=prisma/schema.prisma copy showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String @db.VarChar(255) content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int @@index(authorId) } model Profile { id Int @id @default(autoincrement()) bio String? user User @relation(fields: [userId], references: [id]) userId Int @unique @@index(userId) } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] profile Profile? } ``` You are now ready to push your new schema to your database. Connect to your `main` branch using the instructions in [Connect your database](/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-planetscale). Now use the `db push` CLI command to push to the `main` branch: ```terminal npx prisma db push ``` Great, you now created three tables in your database with Prisma's `db push` command 🚀 --- # Using Prisma Migrate URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-postgresql ## Creating the database schema In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following data model to your [Prisma schema](/orm/prisma-schema) in `prisma/schema.prisma`: ```prisma file=prisma/schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String @db.VarChar(255) content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int } model Profile { id Int @id @default(autoincrement()) bio String? user User @relation(fields: [userId], references: [id]) userId Int @unique } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] profile Profile? } ``` To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: ```terminal npx prisma migrate dev --name init ``` This command does two things: 1. It creates a new SQL migration file for this migration 1. It runs the SQL migration file against the database :::note `generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. ::: Great, you now created three tables in your database with Prisma Migrate 🚀 --- # Using Prisma Migrate URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-node-sqlserver ## Creating the database schema In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: ```prisma file=prisma/schema.prisma copy showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String @db.VarChar(255) content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int } model Profile { id Int @id @default(autoincrement()) bio String? user User @relation(fields: [userId], references: [id]) userId Int @unique } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] profile Profile? } ``` To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: ```terminal npx prisma migrate dev --name init ``` This command does two things: 1. It creates a new SQL migration file for this migration 1. It runs the SQL migration file against the database > **Note**: `generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. Great, you now created three tables in your database with Prisma Migrate 🚀 --- # Using Prisma Migrate URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-cockroachdb ## Creating the database schema In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: ```prisma file=prisma/schema.prisma copy showLineNumbers model Post { id BigInt @id @default(sequence()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId BigInt } model Profile { id BigInt @id @default(sequence()) bio String? user User @relation(fields: [userId], references: [id]) userId BigInt @unique } model User { id BigInt @id @default(sequence()) email String @unique name String? posts Post[] profile Profile? } ``` To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: ```terminal npx prisma migrate dev --name init ``` This command does two things: 1. It creates a new SQL migration file for this migration 1. It runs the SQL migration file against the database :::note `generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. ::: Great, you now created three tables in your database with Prisma Migrate 🚀 --- # Using Prisma Migrate URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-mysql ## Creating the database schema In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: ```prisma file=prisma/schema.prisma copy showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String @db.VarChar(255) content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int } model Profile { id Int @id @default(autoincrement()) bio String? user User @relation(fields: [userId], references: [id]) userId Int @unique } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] profile Profile? } ``` To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: ```terminal npx prisma migrate dev --name init ``` This command does two things: 1. It creates a new SQL migration file for this migration 1. It runs the SQL migration file against the database > **Note**: `generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. Great, you now created three tables in your database with Prisma Migrate 🚀 --- # Using Prisma Migrate URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-planetscale ## Creating the database schema In this guide, you'll use Prisma's [`db push` command](/orm/prisma-migrate/workflows/prototyping-your-schema) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: ```prisma file=prisma/schema.prisma copy showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String @db.VarChar(255) content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int @@index(authorId) } model Profile { id Int @id @default(autoincrement()) bio String? user User @relation(fields: [userId], references: [id]) userId Int @unique @@index(userId) } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] profile Profile? } ``` You are now ready to push your new schema to your database. Connect to your `main` branch using the instructions in [Connect your database](/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-planetscale). Now use the `db push` CLI command to push to the `main` branch: ```terminal npx prisma db push ``` Great, you now created three tables in your database with Prisma's `db push` command 🚀 --- # Using Prisma Migrate URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-postgresql ## Creating the database schema In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following data model to your [Prisma schema](/orm/prisma-schema) in `prisma/schema.prisma`: ```prisma file=prisma/schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String @db.VarChar(255) content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int } model Profile { id Int @id @default(autoincrement()) bio String? user User @relation(fields: [userId], references: [id]) userId Int @unique } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] profile Profile? } ``` To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: ```terminal npx prisma migrate dev --name init ``` This command does two things: 1. It creates a new SQL migration file for this migration 1. It runs the SQL migration file against the database :::note `generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. ::: Great, you now created three tables in your database with Prisma Migrate 🚀 --- # Using Prisma Migrate URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-prismaPostgres ## Creating the database schema In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. To do so, first add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: ```prisma file=prisma/schema.prisma copy model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int } model Profile { id Int @id @default(autoincrement()) bio String? user User @relation(fields: [userId], references: [id]) userId Int @unique } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] profile Profile? } ``` This data model defines three [models](/orm/prisma-schema/data-model/models) (which will be mapped to _tables_ in the underlying database): - `Post` - `Profile` - `User` It also defines two [relations](/orm/prisma-schema/data-model/relations): - A one-to-many relation between `User` and `Post` (i.e. "_one_ user can have _many_ posts") - A one-to-one relation between `User` and `Profile` (i.e. "_one_ user can have _one_ profile") To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: ```terminal npx prisma migrate dev --name init ``` This command did two things: 1. It generated a new SQL migration file for this migration 1. It ran the SQL migration file against the database You can inspect the generated SQL migration file in the newly created `prisma/migrations` directory. :::tip Explore your database in Prisma Studio [Prisma Studio](/orm/tools/prisma-studio) is a visual editor for your database. You can open it with the following command in your terminal: ``` npx prisma studio ``` Since you just created the database, you won't see any records but you can take a look at the empty `User`, `Post` and `Profile` tables. ::: Great, you now created three tables in your database with Prisma Migrate. In the next section, you'll learn how to install Prisma Client which lets you send queries to your database from your TypeScript app. --- # Using Prisma Migrate URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/using-prisma-migrate-typescript-sqlserver ## Creating the database schema In this guide, you'll use [Prisma Migrate](/orm/prisma-migrate) to create the tables in your database. Add the following Prisma data model to your Prisma schema in `prisma/schema.prisma`: ```prisma file=prisma/schema.prisma copy showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String @db.VarChar(255) content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int } model Profile { id Int @id @default(autoincrement()) bio String? user User @relation(fields: [userId], references: [id]) userId Int @unique } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] profile Profile? } ``` To map your data model to the database schema, you need to use the `prisma migrate` CLI commands: ```terminal npx prisma migrate dev --name init ``` This command does two things: 1. It creates a new SQL migration file for this migration 1. It runs the SQL migration file against the database > **Note**: `generate` is called under the hood by default, after running `prisma migrate dev`. If the `prisma-client-js` generator is defined in your schema, this will check if `@prisma/client` is installed and install it if it's missing. Great, you now created three tables in your database with Prisma Migrate 🚀 --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-cockroachdb import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-mysql import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-planetscale import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-postgresql import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-node-sqlserver import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-cockroachdb import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-mysql import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-planetscale import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-postgresql import InstallPrismaClient from './_install-prisma-client-partial.mdx' These commands serve different purposes in managing your database schema with Prisma. Here’s a breakdown of when and why to use each: #### `npx prisma migrate dev` - **Purpose:** This command generates and applies a new migration based on your Prisma schema changes. It creates migration files that keep a history of changes. - **Use Case:** Use this when you want to maintain a record of database changes, which is essential for production environments or when working in teams. It allows for version control of your database schema. - **Benefits:** This command also includes checks for applying migrations in a controlled manner, ensuring data integrity. #### `npx prisma db push` - **Purpose:** This command is used to push your current Prisma schema to the database directly. It applies any changes you've made to your schema without creating migration files. - **Use Case:** It’s particularly useful during the development phase when you want to quickly sync your database schema with your Prisma schema without worrying about migration history. - **Caution:** It can overwrite data if your schema changes affect existing tables or columns, so it’s best for early-stage development or prototyping. --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-prismaPostgres import InstallPrismaClient from './_install-prisma-client-partial.mdx' ## Install the Prisma Accelerate extension Since Prisma Postgres provides a connection pool and (optional) caching layer with Prisma Accelerate, you need to install the Accelerate [Client extension](/orm/prisma-client/client-extensions) in your project as well: ``` npm install @prisma/extension-accelerate ``` With that you're all set to read and write data in your database. Move on to the next page to start querying your Prisma Postgres database using Prisma Client. --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/install-prisma-client-typescript-sqlserver import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-cockroachdb ## Write your first query with Prisma Client Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. Create a new file named `index.js` and add the following code to it: ```js file=index.js copy showLineNumbers const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```js file=index.js highlight=2;delete|3,4;add showLineNumbers async function main() { //delete-next-line // ... you will write your Prisma Client queries here //add-start const allUsers = await prisma.user.findMany() console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy node index.js ``` This should print an empty array because there are no `User` records in the database yet: ```json no-lines [] ``` ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```js file=index.js highlight=2-21;add copy showLineNumbers async function main() { //add-start await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) //add-end } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy node index.js ``` The output should look similar to this: ```js no-lines [ { email: 'alice@prisma.io', id: 1, name: 'Alice', posts: [ { content: null, createdAt: 2020-03-21T16:45:01.246Z, updatedAt: 2020-03-21T16:45:01.246Z, id: 1, published: false, title: 'Hello World', authorId: 1, } ], profile: { bio: 'I like turtles', id: 1, userId: 1, } } ] ``` The query added new records to the `User` and the `Post` tables: **User** | **id** | **email** | **name** | | :----- | :------------------ | :-------- | | `1` | `"alice@prisma.io"` | `"Alice"` | **Post** | **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | | :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | | `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | **Profile** | **id** | **bio** | **userId** | | :----- | :----------------- | :--------- | | `1` | `"I like turtles"` | `1` | > **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```js file=index.js copy showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy node index.js ``` You will see the following output: ```js no-lines { id: 1, title: 'Hello World', content: null, published: true, authorId: 1 } ``` The `Post` record with an `id` of `1` now got updated in the database: **Post** | **id** | **title** | **content** | **published** | **authorId** | | :----- | :-------------- | :---------- | :------------ | :----------- | | `1` | `"Hello World"` | `null` | `true` | `1` | Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-mysql ## Write your first query with Prisma Client Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. Create a new file named `index.js` and add the following code to it: ```js file=index.js copy showLineNumbers const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```js file=index.js highlight=2;delete|3,4; showLineNumbers async function main() { //delete-next-line // ... you will write your Prisma Client queries here //add-start const allUsers = await prisma.user.findMany() console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy node index.js ``` This should print an empty array because there are no `User` records in the database yet: ```json no-lines [] ``` ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```js file=index.js highlight=2-21;add copy showLineNumbers async function main() { //add-start await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) //add-end } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy node index.js ``` The output should look similar to this: ```js no-lines [ { email: 'alice@prisma.io', id: 1, name: 'Alice', posts: [ { content: null, createdAt: 2020-03-21T16:45:01.246Z, updatedAt: 2020-03-21T16:45:01.246Z, id: 1, published: false, title: 'Hello World', authorId: 1, } ], profile: { bio: 'I like turtles', id: 1, userId: 1, } } ] ``` The query added new records to the `User` and the `Post` tables: **User** | **id** | **email** | **name** | | :----- | :------------------ | :-------- | | `1` | `"alice@prisma.io"` | `"Alice"` | **Post** | **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | | :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | | `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | **Profile** | **id** | **bio** | **userId** | | :----- | :----------------- | :--------- | | `1` | `"I like turtles"` | `1` | > **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```js file=index.js copy showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy node index.js ``` You will see the following output: ```js no-lines { id: 1, title: 'Hello World', content: null, published: true, authorId: 1 } ``` The `Post` record with an `id` of `1` now got updated in the database: **Post** | **id** | **title** | **content** | **published** | **authorId** | | :----- | :-------------- | :---------- | :------------ | :----------- | | `1` | `"Hello World"` | `null` | `true` | `1` | Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-planetscale ## Write your first query with Prisma Client Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. Create a new file named `index.js` and add the following code to it: ```js file=index.js copy showLineNumbers const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```js file=index.js highlight=2;delete|3,4;add showLineNumbers async function main() { //delete-next-line // ... you will write your Prisma Client queries here //add-start const allUsers = await prisma.user.findMany() console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy node index.js ``` This should print an empty array because there are no `User` records in the database yet: ```json no-lines [] ``` ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```js file=index.js highlight=2-21;add copy showLineNumbers async function main() { //add-start await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) //add-end } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy node index.js ``` The output should look similar to this: ```js no-lines [ { email: 'alice@prisma.io', id: 1, name: 'Alice', posts: [ { content: null, createdAt: 2020-03-21T16:45:01.246Z, updatedAt: 2020-03-21T16:45:01.246Z, id: 1, published: false, title: 'Hello World', authorId: 1, } ], profile: { bio: 'I like turtles', id: 1, userId: 1, } } ] ``` The query added new records to the `User` and the `Post` tables: **User** | **id** | **email** | **name** | | :----- | :------------------ | :-------- | | `1` | `"alice@prisma.io"` | `"Alice"` | **Post** | **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | | :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | | `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | **Profile** | **id** | **bio** | **userId** | | :----- | :----------------- | :--------- | | `1` | `"I like turtles"` | `1` | > **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```js file=index.js copy showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy node index.js ``` You will see the following output: ```js no-lines { id: 1, title: 'Hello World', content: null, published: true, authorId: 1 } ``` The `Post` record with an `id` of `1` now got updated in the database: **Post** | **id** | **title** | **content** | **published** | **authorId** | | :----- | :-------------- | :---------- | :------------ | :----------- | | `1` | `"Hello World"` | `null` | `true` | `1` | Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-postgresql ## Write your first query with Prisma Client Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. Create a new file named `index.js` and add the following code to it: ```js file=index.js copy showLineNumbers const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```js file=index.js highlight=2;delete|3,4;add showLineNumbers async function main() { //delete-next-line // ... you will write your Prisma Client queries here //add-start const allUsers = await prisma.user.findMany() console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy node index.js ``` This should print an empty array because there are no `User` records in the database yet: ```json no-lines [] ``` ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```js file=index.js highlight=2-21;add copy showLineNumbers async function main() { //add-start await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) //add-end } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy node index.js ``` The output should look similar to this: ```js no-lines [ { email: 'alice@prisma.io', id: 1, name: 'Alice', posts: [ { content: null, createdAt: 2020-03-21T16:45:01.246Z, updatedAt: 2020-03-21T16:45:01.246Z, id: 1, published: false, title: 'Hello World', authorId: 1, } ], profile: { bio: 'I like turtles', id: 1, userId: 1, } } ] ``` The query added new records to the `User` and the `Post` tables: **User** | **id** | **email** | **name** | | :----- | :------------------ | :-------- | | `1` | `"alice@prisma.io"` | `"Alice"` | **Post** | **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | | :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | | `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | **Profile** | **id** | **bio** | **userId** | | :----- | :----------------- | :--------- | | `1` | `"I like turtles"` | `1` | > **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```js file=index.js copy showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy node index.js ``` You will see the following output: ```js no-lines { id: 1, title: 'Hello World', content: null, published: true, authorId: 1 } ``` The `Post` record with an `id` of `1` now got updated in the database: **Post** | **id** | **title** | **content** | **published** | **authorId** | | :----- | :-------------- | :---------- | :------------ | :----------- | | `1` | `"Hello World"` | `null` | `true` | `1` | Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-node-sqlserver ## Write your first query with Prisma Client Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. Create a new file named `index.js` and add the following code to it: ```js file=index.js copy showLineNumbers const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```js file=index.js highlight=2;delete|3,4;add showLineNumbers async function main() { //delete-next-line // ... you will write your Prisma Client queries here //add-start const allUsers = await prisma.user.findMany() console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy node index.js ``` This should print an empty array because there are no `User` records in the database yet: ```json no-lines [] ``` ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```js file=index.js highlight=2-21;add copy showLineNumbers async function main() { //add-start await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) //add-end } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy node index.js ``` The output should look similar to this: ```js no-lines [ { email: 'alice@prisma.io', id: 1, name: 'Alice', posts: [ { content: null, createdAt: 2020-03-21T16:45:01.246Z, updatedAt: 2020-03-21T16:45:01.246Z, id: 1, published: false, title: 'Hello World', authorId: 1, } ], profile: { bio: 'I like turtles', id: 1, userId: 1, } } ] ``` The query added new records to the `User` and the `Post` tables: **User** | **id** | **email** | **name** | | :----- | :------------------ | :-------- | | `1` | `"alice@prisma.io"` | `"Alice"` | **Post** | **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | | :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | | `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | **Profile** | **id** | **bio** | **userId** | | :----- | :----------------- | :--------- | | `1` | `"I like turtles"` | `1` | > **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```js file=index.js copy showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy node index.js ``` You will see the following output: ```js no-lines { id: 1, title: 'Hello World', content: null, published: true, authorId: 1 } ``` The `Post` record with an `id` of `1` now got updated in the database: **Post** | **id** | **title** | **content** | **published** | **authorId** | | :----- | :-------------- | :---------- | :------------ | :----------- | | `1` | `"Hello World"` | `null` | `true` | `1` | Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-cockroachdb ## Write your first query with Prisma Client Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. Create a new file named `index.ts` and add the following code to it: ```js file=index.ts copy showLineNumbers import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```ts file=index.ts highlight=3,4;add showLineNumbers async function main() { // ... you will write your Prisma Client queries here //add-start const allUsers = await prisma.user.findMany() console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy npx tsx index.ts ``` This should print an empty array because there are no `User` records in the database yet: ```json no-lines [] ``` ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```ts file=index.ts highlight=2-21;add copy showLineNumbers async function main() { //add-start await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) //add-end } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy npx tsx index.ts ``` The output should look similar to this: ```js no-lines [ { email: 'alice@prisma.io', id: 1, name: 'Alice', posts: [ { content: null, createdAt: 2020-03-21T16:45:01.246Z, updatedAt: 2020-03-21T16:45:01.246Z, id: 1, published: false, title: 'Hello World', authorId: 1, } ], profile: { bio: 'I like turtles', id: 1, userId: 1, } } ] ``` Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: ```ts no-lines const allUsers: (User & { posts: Post[] })[] export type Post = { id: number title: string content: string | null published: boolean authorId: number | null } ``` The query added new records to the `User` and the `Post` tables: **User** | **id** | **email** | **name** | | :----- | :------------------ | :-------- | | `1` | `"alice@prisma.io"` | `"Alice"` | **Post** | **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | | :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | | `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | **Profile** | **id** | **bio** | **userId** | | :----- | :----------------- | :--------- | | `1` | `"I like turtles"` | `1` | > **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```ts file=index.ts copy showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy npx tsx index.ts ``` You will see the following output: ```js no-lines { id: 1, title: 'Hello World', content: null, published: true, authorId: 1 } ``` The `Post` record with an `id` of `1` now got updated in the database: **Post** | **id** | **title** | **content** | **published** | **authorId** | | :----- | :-------------- | :---------- | :------------ | :----------- | | `1` | `"Hello World"` | `null` | `true` | `1` | Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-mysql ## Write your first query with Prisma Client Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. Create a new file named `index.ts` and add the following code to it: ```js file=index.ts copy showLineNumbers import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```ts file=index.ts highlight=3,4;add showLineNumbers async function main() { // ... you will write your Prisma Client queries here //add-start const allUsers = await prisma.user.findMany() console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy npx tsx index.ts ``` This should print an empty array because there are no `User` records in the database yet: ```json no-lines [] ``` ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```ts file=index.ts highlight=2-21;add copy showLineNumbers async function main() { //add-start await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) //add-end } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy npx tsx index.ts ``` The output should look similar to this: ```js no-lines [ { email: 'alice@prisma.io', id: 1, name: 'Alice', posts: [ { content: null, createdAt: 2020-03-21T16:45:01.246Z, updatedAt: 2020-03-21T16:45:01.246Z, id: 1, published: false, title: 'Hello World', authorId: 1, } ], profile: { bio: 'I like turtles', id: 1, userId: 1, } } ] ``` Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: ```ts no-lines const allUsers: (User & { posts: Post[] })[] export type Post = { id: number title: string content: string | null published: boolean authorId: number | null } ``` The query added new records to the `User` and the `Post` tables: **User** | **id** | **email** | **name** | | :----- | :------------------ | :-------- | | `1` | `"alice@prisma.io"` | `"Alice"` | **Post** | **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | | :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | | `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | **Profile** | **id** | **bio** | **userId** | | :----- | :----------------- | :--------- | | `1` | `"I like turtles"` | `1` | > **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```ts file=index.ts copy showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy npx tsx index.ts ``` You will see the following output: ```js no-lines { id: 1, title: 'Hello World', content: null, published: true, authorId: 1 } ``` The `Post` record with an `id` of `1` now got updated in the database: **Post** | **id** | **title** | **content** | **published** | **authorId** | | :----- | :-------------- | :---------- | :------------ | :----------- | | `1` | `"Hello World"` | `null` | `true` | `1` | Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-planetscale ## Write your first query with Prisma Client Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. Create a new file named `index.ts` and add the following code to it: ```js file=index.ts copy showLineNumbers import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```ts file=index.ts highlight=3,4;add showLineNumbers async function main() { // ... you will write your Prisma Client queries here //add-start const allUsers = await prisma.user.findMany() console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy npx tsx index.ts ``` This should print an empty array because there are no `User` records in the database yet: ```json no-lines [] ``` ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```ts file=index.ts highlight=2-21;add copy showLineNumbers async function main() { //add-start await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) //add-end } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy npx tsx index.ts ``` The output should look similar to this: ```js no-lines [ { email: 'alice@prisma.io', id: 1, name: 'Alice', posts: [ { content: null, createdAt: 2020-03-21T16:45:01.246Z, updatedAt: 2020-03-21T16:45:01.246Z, id: 1, published: false, title: 'Hello World', authorId: 1, } ], profile: { bio: 'I like turtles', id: 1, userId: 1, } } ] ``` Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: ```ts no-lines const allUsers: (User & { posts: Post[] })[] export type Post = { id: number title: string content: string | null published: boolean authorId: number | null } ``` The query added new records to the `User` and the `Post` tables: **User** | **id** | **email** | **name** | | :----- | :------------------ | :-------- | | `1` | `"alice@prisma.io"` | `"Alice"` | **Post** | **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | | :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | | `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | **Profile** | **id** | **bio** | **userId** | | :----- | :----------------- | :--------- | | `1` | `"I like turtles"` | `1` | > **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```ts file=index.ts copy showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy npx tsx index.ts ``` You will see the following output: ```js no-lines { id: 1, title: 'Hello World', content: null, published: true, authorId: 1 } ``` The `Post` record with an `id` of `1` now got updated in the database: **Post** | **id** | **title** | **content** | **published** | **authorId** | | :----- | :-------------- | :---------- | :------------ | :----------- | | `1` | `"Hello World"` | `null` | `true` | `1` | Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-postgresql ## Write your first query with Prisma Client Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. Create a new file named `index.ts` and add the following code to it: ```js file=index.ts copy showLineNumbers import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```ts file=index.ts highlight=3,4;add showLineNumbers async function main() { // ... you will write your Prisma Client queries here //add-start const allUsers = await prisma.user.findMany() console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy npx tsx index.ts ``` This should print an empty array because there are no `User` records in the database yet: ```json no-lines [] ``` ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```ts file=index.ts highlight=2-21;add copy showLineNumbers async function main() { //add-start await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) //add-end } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy npx tsx index.ts ``` The output should look similar to this: ```js no-lines [ { email: 'alice@prisma.io', id: 1, name: 'Alice', posts: [ { content: null, createdAt: 2020-03-21T16:45:01.246Z, updatedAt: 2020-03-21T16:45:01.246Z, id: 1, published: false, title: 'Hello World', authorId: 1, } ], profile: { bio: 'I like turtles', id: 1, userId: 1, } } ] ``` Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: ```ts no-lines const allUsers: (User & { posts: Post[] })[] export type Post = { id: number title: string content: string | null published: boolean authorId: number | null } ``` The query added new records to the `User` and the `Post` tables: **User** | **id** | **email** | **name** | | :----- | :------------------ | :-------- | | `1` | `"alice@prisma.io"` | `"Alice"` | **Post** | **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | | :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | | `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | **Profile** | **id** | **bio** | **userId** | | :----- | :----------------- | :--------- | | `1` | `"I like turtles"` | `1` | > **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```ts file=index.ts copy showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy npx tsx index.ts ``` You will see the following output: ```js no-lines { id: 1, title: 'Hello World', content: null, published: true, authorId: 1 } ``` The `Post` record with an `id` of `1` now got updated in the database: **Post** | **id** | **title** | **content** | **published** | **authorId** | | :----- | :-------------- | :---------- | :------------ | :----------- | | `1` | `"Hello World"` | `null` | `true` | `1` | Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-prismaPostgres ## Write your first query with Prisma Client Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain TypeScript script to explore some basic features of Prisma Client. Create a new file named `queries.ts` and add the following code to it: ```js file=queries.ts copy // 1 import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' // 2 const prisma = new PrismaClient() .$extends(withAccelerate()) // 3 async function main() { // ... you will write your Prisma Client queries here } // 4 main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) // 5 await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor and the `withAccelerate` extension. 1. Instantiate `PrismaClient` and add the Accelerate extension. 1. Define an `async` function named `main` to send queries to the database. 1. Call the `main` function. 1. Close the database connections when the script terminates. Inside the `main` function, add the following query to read all `User` records from the database and log the result: ```ts file=queries.ts async function main() { //add-start const allUsers = await prisma.user.findMany() console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy npx tsx queries.ts ``` This should print an empty array because there are no `User` records in the database yet: ```json no-lines [] ``` ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post`, `User` and `Profile` tables all at once. Adjust the `main` function by removing the code from before and adding the following: ```ts file=queries.ts highlight=2-21;add copy async function main() { //add-start await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) //add-end } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The records are connected via the [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) that you defined in your Prisma schema. Notice that you're also passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy npx tsx queries.ts ``` The output should look similar to this: ```js no-copy showLineNumbers [ { email: 'alice@prisma.io', id: 1, name: 'Alice', posts: [ { content: null, createdAt: 2020-03-21T16:45:01.246Z, updatedAt: 2020-03-21T16:45:01.246Z, id: 1, published: false, title: 'Hello World', authorId: 1, } ], profile: { bio: 'I like turtles', id: 1, userId: 1, } } ] ``` Also note that the `allUsers` variable is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: ```ts no-copy showLineNumbers const allUsers: ({ posts: { id: number; createdAt: Date; updatedAt: Date; title: string; content: string | null; published: boolean; authorId: number; }[]; profile: { id: number; bio: string | null; userId: number; } | null; } & { ...; })[] ```
Expand for a visual view of the records that have been created The query added new records to the `User`, `Post`, and `Profile` tables: **User** | **id** | **email** | **name** | | :----- | :------------------ | :-------- | | `1` | `"alice@prisma.io"` | `"Alice"` | **Post** | **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | | :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | | `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | **Profile** | **id** | **bio** | **userId** | | :----- | :----------------- | :--------- | | `1` | `"I like turtles"` | `1` | The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database.
Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```ts file=queries.ts copy async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy npx tsx queries.ts ``` You will see the following output: ```js no-lines { id: 1, title: 'Hello World', content: null, published: true, authorId: 1 } ``` The `Post` record with an `id` of `1` now got updated in the database: **Post** | **id** | **title** | **content** | **published** | **authorId** | | :----- | :-------------- | :---------- | :------------ | :----------- | | `1` | `"Hello World"` | `null` | `true` | `1` | Congratulations! You've now learned how to query a Prisma Postgres database with Prisma Client in your application. If you got lost along the way, want to learn about more queries or explore the caching feature of Prisma Accelerate, check out the comprehensive [Prisma starter template](https://github.com/prisma/prisma-examples/tree/latest/databases/prisma-postgres). --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/querying-the-database-typescript-sqlserver ## Write your first query with Prisma Client Now that you have generated [Prisma Client](/orm/prisma-client), you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. Create a new file named `index.ts` and add the following code to it: ```js file=index.ts copy showLineNumbers import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```ts file=index.ts highlight=3,4;add showLineNumbers async function main() { // ... you will write your Prisma Client queries here //add-start const allUsers = await prisma.user.findMany() console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy npx tsx index.ts ``` This should print an empty array because there are no `User` records in the database yet: ```json no-lines [] ``` ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```ts file=index.ts highlight=2-21;add copy showLineNumbers async function main() { //add-start await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) //add-end } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy npx tsx index.ts ``` The output should look similar to this: ```js no-lines [ { email: 'alice@prisma.io', id: 1, name: 'Alice', posts: [ { content: null, createdAt: 2020-03-21T16:45:01.246Z, updatedAt: 2020-03-21T16:45:01.246Z, id: 1, published: false, title: 'Hello World', authorId: 1, } ], profile: { bio: 'I like turtles', id: 1, userId: 1, } } ] ``` Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: ```ts no-lines const allUsers: (User & { posts: Post[] })[] export type Post = { id: number title: string content: string | null published: boolean authorId: number | null } ``` The query added new records to the `User` and the `Post` tables: **User** | **id** | **email** | **name** | | :----- | :------------------ | :-------- | | `1` | `"alice@prisma.io"` | `"Alice"` | **Post** | **id** | **createdAt** | **updatedAt** | **title** | **content** | **published** | **authorId** | | :----- | :------------------------- | :------------------------: | :-------------- | :---------- | :------------ | :----------- | | `1` | `2020-03-21T16:45:01.246Z` | `2020-03-21T16:45:01.246Z` | `"Hello World"` | `null` | `false` | `1` | **Profile** | **id** | **bio** | **userId** | | :----- | :----------------- | :--------- | | `1` | `"I like turtles"` | `1` | > **Note**: The numbers in the `authorId` column on `Post` and `userId` column on `Profile` both reference the `id` column of the `User` table, meaning the `id` value `1` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```ts file=index.ts copy showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy npx tsx index.ts ``` You will see the following output: ```js no-lines { id: 1, title: 'Hello World', content: null, published: true, authorId: 1 } ``` The `Post` record with an `id` of `1` now got updated in the database: **Post** | **id** | **title** | **content** | **published** | **authorId** | | :----- | :-------------- | :---------- | :------------ | :----------- | | `1` | `"Hello World"` | `null` | `true` | `1` | Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Next steps URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases/next-steps This section lists a number of potential next steps you can now take from here. Feel free to explore these or read the [Introduction](/orm/overview/introduction/what-is-prisma) page to get a high-level overview of Prisma ORM. ### Continue exploring the Prisma Client API You can send a variety of queries with the Prisma Client API. Check out the [API reference](/orm/prisma-client) and use your existing database setup from this guide to try them out. :::tip You can use your editor's auto-completion feature to learn about the different API calls and the arguments it takes. Auto-completion is commonly invoked by hitting CTRL+SPACE on your keyboard. :::
Expand for more Prisma Client API examples Here are a few suggestions for a number of more queries you can send with Prisma Client: **Filter all `Post` records that contain `"hello"`** ```js const filteredPosts = await prisma.post.findMany({ where: { OR: [{ title: { contains: 'hello' } }, { content: { contains: 'hello' } }], }, }) ``` **Create a new `Post` record and connect it to an existing `User` record** ```js const post = await prisma.post.create({ data: { title: 'Join us for Prisma Day 2020', author: { connect: { email: 'alice@prisma.io' }, }, }, }) ``` **Use the fluent relations API to retrieve the `Post` records of a `User` by traversing the relations** ```js const posts = await prisma.profile .findUnique({ where: { id: 1 }, }) .user() .posts() ``` **Delete a `User` record** ```js const deletedUser = await prisma.user.delete({ where: { email: 'sarah@prisma.io' }, }) ```
### Build an app with Prisma ORM The Prisma blog features comprehensive tutorials about Prisma ORM, check out our latest ones: - [Build a fullstack app with Next.js](https://www.youtube.com/watch?v=QXxy8Uv1LnQ&ab_channel=ByteGrad) - [Build a fullstack app with Remix](https://www.prisma.io/blog/fullstack-remix-prisma-mongodb-1-7D0BfTXBmB6r) (5 parts, including videos) - [Build a REST API with NestJS](https://www.prisma.io/blog/nestjs-prisma-rest-api-7D056s1BmOL0) ### Explore the data in Prisma Studio Prisma Studio is a visual editor for the data in your database. Run `npx prisma studio` in your terminal. If you are using [Prisma Postgres](https://www.prisma.io/postgres), you can also directly use Prisma Studio inside the [Console](https://console.prisma.io) by selecting the **Studio** tab in your project. ### Get query insights and analytics with Prisma Optimize [Prisma Optimize](/optimize) helps you generate insights and provides recommendations that can help you make your database queries faster. [Try it out now!](/optimize/getting-started) Optimize aims to help developers of all skill levels write efficient database queries, reducing database load and making applications more responsive. ### Try a Prisma ORM example The [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository contains a number of ready-to-run examples: | Demo | Stack | Description | | :------------------------------------------------------------------------------------------------------------------ | :----------- | --------------------------------------------------------------------------------------------------- | | [`nextjs`](https://pris.ly/e/orm/nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app | | [`nextjs-graphql`](https://pris.ly/e/ts/graphql-nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app (React) with a GraphQL API | | [`graphql-nexus`](https://pris.ly/e/ts/graphql-nexus) | Backend only | GraphQL server based on [`@apollo/server`](https://www.apollographql.com/docs/apollo-server) | | [`express`](https://pris.ly/e/ts/rest-express) | Backend only | Simple REST API with Express.JS | | [`grpc`](https://pris.ly/e/ts/grpc) | Backend only | Simple gRPC API | --- ## Install and generate Prisma Client To get started with Prisma Client, first install the `@prisma/client` package: ```terminal copy npm install @prisma/client ``` Then, run `prisma generate` which reads your Prisma schema and generates the Prisma Client. ```terminal copy npx prisma generate ``` You can now import the `PrismaClient` constructor from the `@prisma/client` package to create an instance of Prisma Client to send queries to your database. You'll learn how to do that in the next section. :::note Good to know When you run `prisma generate`, you are actually creating code (TypeScript types, methods, queries, ...) that is tailored to _your_ Prisma schema file or files in the `prisma` directory. This means, that whenever you make changes to your Prisma schema file, you also need to update the Prisma Client. You can do this by running the `prisma generate` command. ![Install and generate Prisma Client](/img/getting-started/prisma-client-install-and-generate.png) Whenever you update your Prisma schema, you will have to update your database schema using either `prisma migrate dev` or `prisma db push`. This will keep your database schema in sync with your Prisma schema. These commands will also run `prisma generate` under the hood to re-generate your Prisma Client. ::: --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-node-cockroachdb Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [CockroachDB](https://www.cockroachlabs.com/) database server running > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Create project setup As a first step, create a project directory and navigate into it: ```terminal copy mkdir hello-prisma cd hello-prisma ``` Next, initialize a Node.js project and add the Prisma CLI as a development dependency to it: ```terminal copy npm init -y npm install prisma --save-dev ``` This creates a `package.json` with an initial setup for a Node.js app. --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-node-mysql Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [MySQL](https://www.mysql.com/) database server running > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Create project setup As a first step, create a project directory and navigate into it: ```terminal copy mkdir hello-prisma cd hello-prisma ``` Next, initialize a Node.js project and add the Prisma CLI as a development dependency to it: ```terminal copy npm init -y npm install prisma --save-dev ``` This creates a `package.json` with an initial setup for a Node.js app. :::info See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-node-planetscale Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [PlanetScale](https://planetscale.com/) database server running This tutorial will also assume that you can push to the `main` branch of your database. Do not do this if your `main` branch has been promoted to production. Next, initialize a Node.js project and add the Prisma CLI as a development dependency to it: ```terminal copy npm init -y npm install prisma --save-dev ``` This creates a `package.json` with an initial setup for a Node.js app. :::info See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-node-postgresql Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [PostgreSQL](https://www.postgresql.org/) database server running > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Create project setup As a first step, create a project directory and navigate into it: ```terminal copy mkdir hello-prisma cd hello-prisma ``` Next, initialize a Node.js project and add the Prisma CLI as a development dependency to it: ```terminal copy npm init -y npm install prisma --save-dev ``` This creates a `package.json` with an initial setup for a Node.js app. :::info See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-node-sqlserver Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - A [Microsoft SQL Server](https://learn.microsoft.com/en-us/sql/?view=sql-server-ver16) database - [Microsoft SQL Server on Linux for Docker](/orm/overview/databases/sql-server/sql-server-docker) - [Microsoft SQL Server on Windows (local)](/orm/overview/databases/sql-server/sql-server-local) > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Create project setup As a first step, create a project directory and navigate into it: ```terminal copy mkdir hello-prisma cd hello-prisma ``` Next, initialize a Node.js project and add the Prisma CLI as a development dependency to it: ```terminal copy npm init -y npm install prisma --save-dev ``` This creates a `package.json` with an initial setup for a Node.js app. :::info See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-cockroachdb Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [CockroachDB](https://www.cockroachlabs.com/) database server running > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Create project setup As a first step, create a project directory and navigate into it: ```terminal copy mkdir hello-prisma cd hello-prisma ``` Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: ```terminal copy npm init -y npm install prisma typescript tsx @types/node --save-dev ``` This creates a `package.json` with an initial setup for your TypeScript app. Next, initialize TypeScript: ```terminal copy npx tsc --init ``` :::info See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-mysql Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [MySQL](https://www.mysql.com/) database server running > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Create project setup As a first step, create a project directory and navigate into it: ```terminal copy mkdir hello-prisma cd hello-prisma ``` Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: ```terminal copy npm init -y npm install prisma typescript tsx @types/node --save-dev ``` This creates a `package.json` with an initial setup for your TypeScript app. Next, initialize TypeScript: ```terminal copy npx tsc --init ``` :::info See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-planetscale Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [PlanetScale](https://planetscale.com/) database server running This tutorial will also assume that you can push to the `main` branch of your database. Do not do this if your `main` branch has been promoted to production. > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Create project setup As a first step, create a project directory and navigate into it: ```terminal copy mkdir hello-prisma cd hello-prisma ``` Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: ```terminal copy npm init -y npm install prisma typescript tsx @types/node --save-dev ``` This creates a `package.json` with an initial setup for your TypeScript app. Next, initialize TypeScript: ```terminal copy npx tsc --init ``` :::info See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [PostgreSQL](https://www.postgresql.org/) database server running > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Create project setup As a first step, create a project directory and navigate into it: ```terminal copy mkdir hello-prisma cd hello-prisma ``` Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: ```terminal copy npm init -y npm install prisma typescript tsx @types/node --save-dev ``` This creates a `package.json` with an initial setup for your TypeScript app. Next, initialize TypeScript: ```terminal copy npx tsc --init ``` :::info See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-prismaPostgres Learn how to create a new TypeScript project with a Prisma Postgres database from scratch. This tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate) and covers the following workflows: - Creating a TypeScript project on your local machine from scratch - Creating a [Prisma Postgres](https://www.prisma.io/postgres?utm_source=docs) database - Schema migrations and queries (via [Prisma ORM](https://www.prisma.io/orm)) - Connection pooling and caching (via [Prisma Accelerate](https://www.prisma.io/accelerate)) ## Prerequisites To successfully complete this tutorial, you need: - a [Prisma Data Platform](https://console.prisma.io/) (PDP) account - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) (see [system requirements](/orm/reference/system-requirements) for officially supported versions) ## Create project setup Create a project directory and navigate into it: ```terminal copy mkdir hello-prisma cd hello-prisma ``` Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: ```terminal copy npm init -y npm install prisma typescript tsx @types/node --save-dev ``` This creates a `package.json` with an initial setup for your TypeScript app. Next, initialize TypeScript: ```terminal copy npx tsc --init ``` You can now invoke the Prisma CLI by prefixing it with `npx`: ```terminal npx prisma ``` Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: ```terminal copy npx prisma init --db --output ../generated/prisma ``` This command does a few things: - Creates a new directory called `prisma` that contains a file called `schema.prisma`, which contains the Prisma Schema with your database connection variable and schema models. - Sets the `output` to a custom location. - Creates a [`.env`](/orm/more/development-environment/environment-variables) file in the root directory of the project, which is used for defining environment variables (such as your database connection and API keys). In the next section, you'll learn how to connect your Prisma Postgres database to the project you just created on your file system. :::info Using version control? If you're using version control, like git, we recommend you add a line to your `.gitignore` in order to exclude the generated client from your application. In this example, we want to exclude the `generated/prisma` directory. ```code file=.gitignore //add-start generated/prisma/ //add-end ``` ::: --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-sqlserver Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - A [Microsoft SQL Server](https://learn.microsoft.com/en-us/sql/?view=sql-server-ver16) database - [Microsoft SQL Server on Linux for Docker](/orm/overview/databases/sql-server/sql-server-docker) - [Microsoft SQL Server on Windows (local)](/orm/overview/databases/sql-server/sql-server-local) > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Create project setup As a first step, create a project directory and navigate into it: ```terminal copy mkdir hello-prisma cd hello-prisma ``` Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: ```terminal copy npm init -y npm install prisma typescript tsx @types/node --save-dev ``` This creates a `package.json` with an initial setup for your TypeScript app. Next, initialize TypeScript: ```terminal copy npx tsc --init ``` :::info See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma using a different package manager. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Connect your database (MongoDB) URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/mongodb/connect-your-database-node-mongodb To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "mongodb" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env` (the example uses a [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) URL): ```bash file=.env showLineNumbers DATABASE_URL="mongodb+srv://test:test@cluster0.ns1yp.mongodb.net/myFirstDatabase" ``` You now need to adjust the connection URL to point to your own database. The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For MongoDB, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines mongodb://USERNAME:PASSWORD@HOST:PORT/DATABASE ``` Here's a short explanation of each component: - `USERNAME`: The name of your database user - `PASSWORD`: The password for your database user - `HOST`: The host where a [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) (or [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos/#mongodb-binary-bin.mongos)) instance is running - `PORT`: The port where your database server is running (typically `27017` for MongoDB) - `DATABASE`: The name of the database. Note that if you're using MongoDB Atlas, you need to manually append the database name to the connection URL because the environment link from MongoDB Atlas doesn't contain it. ## Troubleshooting ### `Error in connector: SCRAM failure: Authentication failed.` If you see the `Error in connector: SCRAM failure: Authentication failed.` error message, you can specify the source database for the authentication by [adding](https://github.com/prisma/prisma/discussions/9994#discussioncomment-1562283) `?authSource=admin` to the end of the connection string. ### `Raw query failed. Error code 8000 (AtlasError): empty database name not allowed.` If you see the `Raw query failed. Code: unknown. Message: Kind: Command failed: Error code 8000 (AtlasError): empty database name not allowed.` error message, be sure to append the database name to the database URL. You can find more info in this [GitHub issue](https://github.com/prisma/docs/issues/5562). --- # Connect your database (MongoDB) URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/mongodb/connect-your-database-typescript-mongodb To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "mongodb" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env` (the example uses a [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) URL): ```bash file=.env showLineNumbers DATABASE_URL="mongodb+srv://test:test@cluster0.ns1yp.mongodb.net/myFirstDatabase" ``` You now need to adjust the connection URL to point to your own database. The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For MongoDB, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines mongodb://USERNAME:PASSWORD@HOST:PORT/DATABASE ``` Here's a short explanation of each component: - `USERNAME`: The name of your database user - `PASSWORD`: The password for your database user - `HOST`: The host where a [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) (or [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos/#mongodb-binary-bin.mongos)) instance is running - `PORT`: The port where your database server is running (typically `27017` for MongoDB) - `DATABASE`: The name of the database. Note that if you're using MongoDB Atlas, you need to manually append the database name to the connection URL because the environment link from MongoDB Atlas doesn't contain it. ## Troubleshooting ### `Error in connector: SCRAM failure: Authentication failed.` If you see the `Error in connector: SCRAM failure: Authentication failed.` error message, you can specify the source database for the authentication by [adding](https://github.com/prisma/prisma/discussions/9994#discussioncomment-1562283) `?authSource=admin` to the end of the connection string. ### `Raw query failed. Error code 8000 (AtlasError): empty database name not allowed.` If you see the `Raw query failed. Code: unknown. Message: Kind: Command failed: Error code 8000 (AtlasError): empty database name not allowed.` error message, be sure to append the database name to the database URL. You can find more info in this [GitHub issue](https://github.com/prisma/docs/issues/5562). --- # Creating the Prisma schema URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/mongodb/creating-the-prisma-schema-node-mongodb ## Update the Prisma schema Open the `prisma/schema.prisma` file and replace the default contents with the following: ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId slug String @unique title String body String author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId comments Comment[] } model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique name String? address Address? posts Post[] } model Comment { id String @id @default(auto()) @map("_id") @db.ObjectId comment String post Post @relation(fields: [postId], references: [id]) postId String @db.ObjectId } // Address is an embedded document type Address { street String city String state String zip String } ``` There are also a number of subtle differences in how the schema is setup when compared to relational databases like PostgreSQL. For example, the underlying `ID` field name is always `_id` and must be mapped with `@map("_id")`. For more information check out the [MongoDB schema reference](/orm/reference/prisma-schema-reference#mongodb-2). --- # Creating the Prisma schema URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/mongodb/creating-the-prisma-schema-typescript-mongodb ## Update the Prisma schema Open the `prisma/schema.prisma` file and replace the default contents with the following: ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId slug String @unique title String body String author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId comments Comment[] } model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique name String? address Address? posts Post[] } model Comment { id String @id @default(auto()) @map("_id") @db.ObjectId comment String post Post @relation(fields: [postId], references: [id]) postId String @db.ObjectId } // Address is an embedded document type Address { street String city String state String zip String } ``` There are also a number of subtle differences in how the schema is setup when compared to relational databases like PostgreSQL. For example, the underlying `ID` field name is always `_id` and must be mapped with `@map("_id")`. For more information check out the [MongoDB schema reference](/orm/reference/prisma-schema-reference#mongodb-2). --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/mongodb/install-prisma-client-node-mongodb ## Install and generate Prisma Client To get started with Prisma Client, you need to install the `@prisma/client` package: ```terminal copy npm install @prisma/client ``` Then, run `prisma generate` which reads your Prisma schema and generates the Prisma Client. ```terminal copy npx prisma generate ``` ![Install and generate Prisma Client](/img/getting-started/prisma-client-install-and-generate.png) Whenever you update your Prisma schema, you will need to run the `prisma db push` command to create new indexes and regenerate Prisma Client. --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/mongodb/install-prisma-client-typescript-mongodb ## Install and generate Prisma Client To get started with Prisma Client, you need to install the `@prisma/client` package: ```terminal copy npm install @prisma/client ``` Then, run `prisma generate` which reads your Prisma schema and generates the Prisma Client. ```terminal copy npx prisma generate ``` ![Install and generate Prisma Client](/img/getting-started/prisma-client-install-and-generate.png) Whenever you update your Prisma schema, you will need to run the `prisma db push` command to create new indexes and regenerate Prisma Client. --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/mongodb/querying-the-database-node-mongodb ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. Create a new file named `index.js` and add the following code to it: ```js file=index.js copy showLineNumbers const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Connect to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```js file=index.js async function main() { //delete-next-line - // ... you will write your Prisma Client queries here //add-start + const allUsers = await prisma.user.findMany() + console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy node index.js ``` This should print an empty array because there are no `User` records in the database yet: ```json no-lines [] ``` ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post`, `User` and `Comment` tables. Adjust the `main` function to send a `create` query to the database: ```js file=index.js highlight=2-21;add copy showLineNumbers async function main() { //add-start await prisma.user.create({ data: { name: 'Rich', email: 'hello@prisma.com', posts: { create: { title: 'My first post', body: 'Lots of really interesting stuff', slug: 'my-first-post', }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, }, }) console.dir(allUsers, { depth: null }) //add-end } ``` This code creates a new `User` record together with a new `Post` using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the other one via the `Post.author` ↔ `User.posts` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` relations on the returned `User` objects. Run the code with this command: ```terminal copy node index.js ``` The output should look similar to this: ```json no-lines [ { id: '60cc9b0e001e3bfd00a6eddf', email: 'hello@prisma.com', name: 'Rich', address: null, posts: [ { id: '60cc9bad005059d6007f45dd', slug: 'my-first-post', title: 'My first post', body: 'Lots of really interesting stuff', userId: '60cc9b0e001e3bfd00a6eddf', }, ], }, ] ``` The query added new records to the `User` and the `Post` tables: **User** | **id** | **email** | **name** | | :------------------------- | :------------------- | :------- | | `60cc9b0e001e3bfd00a6eddf` | `"hello@prisma.com"` | `"Rich"` | **Post** | **id** | **createdAt** | **title** | **content** | **published** | **authorId** | | :------------------------- | :------------------------- | :---------------- | :--------------------------------- | :------------ | :------------------------- | | `60cc9bad005059d6007f45dd` | `2020-03-21T16:45:01.246Z` | `"My first post"` | `Lots of really interesting stuff` | `false` | `60cc9b0e001e3bfd00a6eddf` | > **Note**: The unique IDs in the `authorId` column on `Post` reference the `id` column of the `User` table, meaning the `id` value `60cc9b0e001e3bfd00a6eddf` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll add a couple of comments to the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```js file=index.js copy showLineNumbers async function main() { await prisma.post.update({ where: { slug: 'my-first-post', }, data: { comments: { createMany: { data: [ { comment: 'Great post!' }, { comment: "Can't wait to read more!" }, ], }, }, }, }) const posts = await prisma.post.findMany({ include: { comments: true, }, }) console.dir(posts, { depth: Infinity }) } ``` Now run the code using the same command as before: ```terminal copy node index.js ``` You will see the following output: ```json no-lines [ { id: '60cc9bad005059d6007f45dd', slug: 'my-first-post', title: 'My first post', body: 'Lots of really interesting stuff', userId: '60cc9b0e001e3bfd00a6eddf', comments: [ { id: '60cca420008a21d800578793', postId: '60cca40300af8bf000f6ca99', comment: 'Great post!', }, { id: '60cca420008a21d800578794', postId: '60cca40300af8bf000f6ca99', comment: "Can't wait to try this!", }, ], }, ] ``` Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/mongodb/querying-the-database-typescript-mongodb ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. Create a new file named `index.ts` and add the following code to it: ```js file=index.ts copy showLineNumbers import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .catch(async (e) => { console.error(e) process.exit(1) }) .finally(async () => { await prisma.$disconnect() }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Connect to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```ts file=index.ts showLineNumbers async function main() { // ... you will write your Prisma Client queries here //add-start + const allUsers = await prisma.user.findMany() + console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy npx tsx index.ts ``` This should print an empty array because there are no `User` records in the database yet: ```json no-lines [] ``` ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post`, `User` and `Comment` tables. Adjust the `main` function to send a `create` query to the database: ```ts file=index.ts highlight=2-21;add copy showLineNumbers async function main() { //add-start await prisma.user.create({ data: { name: 'Rich', email: 'hello@prisma.com', posts: { create: { title: 'My first post', body: 'Lots of really interesting stuff', slug: 'my-first-post', }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, }, }) console.dir(allUsers, { depth: null }) //add-end } ``` This code creates a new `User` record together with a new `Post` using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the other one via the `Post.author` ↔ `User.posts` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` relations on the returned `User` objects. Run the code with this command: ```terminal copy npx tsx index.ts ``` The output should look similar to this: ```json no-lines [ { id: '60cc9b0e001e3bfd00a6eddf', email: 'hello@prisma.com', name: 'Rich', address: null, posts: [ { id: '60cc9bad005059d6007f45dd', slug: 'my-first-post', title: 'My first post', body: 'Lots of really interesting stuff', userId: '60cc9b0e001e3bfd00a6eddf', }, ], }, ] ``` Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: ```ts no-lines const allUsers: (User & { posts: Post[] })[] export type Post = { id: number title: string body: string | null published: boolean authorId: number | null } ``` The query added new records to the `User` and the `Post` tables: **User** | **id** | **email** | **name** | | :------------------------- | :------------------- | :------- | | `60cc9b0e001e3bfd00a6eddf` | `"hello@prisma.com"` | `"Rich"` | **Post** | **id** | **createdAt** | **title** | **content** | **published** | **authorId** | | :------------------------- | :------------------------- | :---------------- | :--------------------------------- | :------------ | :------------------------- | | `60cc9bad005059d6007f45dd` | `2020-03-21T16:45:01.246Z` | `"My first post"` | `Lots of really interesting stuff` | `false` | `60cc9b0e001e3bfd00a6eddf` | > **Note**: The unique IDs in the `authorId` column on `Post` reference the `id` column of the `User` table, meaning the `id` value `60cc9b0e001e3bfd00a6eddf` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll add a couple of comments to the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```ts file=index.ts copy showLineNumbers async function main() { await prisma.post.update({ where: { slug: 'my-first-post', }, data: { comments: { createMany: { data: [ { comment: 'Great post!' }, { comment: "Can't wait to read more!" }, ], }, }, }, }) const posts = await prisma.post.findMany({ include: { comments: true, }, }) console.dir(posts, { depth: Infinity }) } ``` Now run the code using the same command as before: ```terminal copy npx tsx index.ts ``` You will see the following output: ```json no-lines [ { id: '60cc9bad005059d6007f45dd', slug: 'my-first-post', title: 'My first post', body: 'Lots of really interesting stuff', userId: '60cc9b0e001e3bfd00a6eddf', comments: [ { id: '60cca420008a21d800578793', postId: '60cca40300af8bf000f6ca99', comment: 'Great post!', }, { id: '60cca420008a21d800578794', postId: '60cca40300af8bf000f6ca99', comment: "Can't wait to try this!", }, ], }, ] ``` Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Next steps URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/mongodb/next-steps This section lists a number of potential next steps you can now take from here. Feel free to explore these or read the [Introduction](/orm/overview/introduction/what-is-prisma) page to get a high-level overview of Prisma ORM. ### Continue exploring the Prisma Client API You can send a variety of queries with the Prisma Client API. Check out the [API reference](/orm/prisma-client) and use your existing database setup from this guide to try them out. :::tip You can use your editor's auto-completion feature to learn about the different API calls and the arguments it takes. Auto-completion is commonly invoked by hitting CTRL+SPACE on your keyboard. :::
Expand for more Prisma Client API examples Here are a few suggestions for a number of more queries you can send with Prisma Client: **Filter all `Post` records that contain `"hello"`** ```js const filteredPosts = await prisma.post.findMany({ where: { OR: [{ title: { contains: 'hello' } }, { body: { contains: 'hello' } }], }, }) ``` **Create a new `Post` record and connect it to an existing `User` record** ```js const post = await prisma.post.create({ data: { title: 'Join us for Prisma Day 2020', slug: 'prisma-day-2020', body: 'A conference on modern application development and databases.', user: { connect: { email: 'hello@prisma.com' }, }, }, }) ``` **Use the fluent relations API to retrieve the `Post` records of a `User` by traversing the relations** ```js const user = await prisma.comment .findUnique({ where: { id: '60ff4e9500acc65700ebf470' }, }) .post() .user() ``` **Delete a `User` record** ```js const deletedUser = await prisma.user.delete({ where: { email: 'sarah@prisma.io' }, }) ```
### Build an app with Prisma ORM The Prisma blog features comprehensive tutorials about Prisma ORM, check out our latest ones: - [Build a fullstack app with Next.js](https://www.youtube.com/watch?v=QXxy8Uv1LnQ&ab_channel=ByteGrad) - [Build a fullstack app with Remix](https://www.prisma.io/blog/fullstack-remix-prisma-mongodb-1-7D0BfTXBmB6r) (5 parts, including videos) - [Build a REST API with NestJS](https://www.prisma.io/blog/nestjs-prisma-rest-api-7D056s1BmOL0) ### Explore the data in Prisma Studio Prisma Studio is a visual editor for the data in your database. Run `npx prisma studio` in your terminal. ### Try a Prisma ORM example The [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository contains a number of ready-to-run examples: | Demo | Stack | Description | | :------------------------------------------------------------------------------------------------------------------ | :----------- | --------------------------------------------------------------------------------------------------- | | [`nextjs`](https://pris.ly/e/orm/nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app | | [`nextjs-graphql`](https://pris.ly/e/ts/graphql-nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app (React) with a GraphQL API | | [`graphql-nexus`](https://pris.ly/e/ts/graphql-nexus) | Backend only | GraphQL server based on [`@apollo/server`](https://www.apollographql.com/docs/apollo-server) | | [`express`](https://pris.ly/e/ts/rest-express) | Backend only | Simple REST API with Express.JS | | [`grpc`](https://pris.ly/e/ts/grpc) | Backend only | Simple gRPC API | --- # MongoDB URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/mongodb-node-mongodb Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your MongoDB database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli) and [Prisma Client](/orm/prisma-client). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - Access to a MongoDB 4.2+ server with a replica set deployment. We recommend using [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). The MongoDB database connector uses transactions to support nested writes. Transactions **require** a [replica set](https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/) deployment. The easiest way to deploy a replica set is with [Atlas](https://www.mongodb.com/docs/atlas/getting-started/). It's free to get started. Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). > See [System requirements](/orm/reference/system-requirements) for exact version requirements. ## Create project setup As a first step, create a project directory and navigate into it: ```terminal copy mkdir hello-prisma cd hello-prisma ``` Next, initialize a Node.js project and add the Prisma CLI as a development dependency to it: ```terminal copy npm init -y npm install prisma --save-dev ``` This creates a `package.json` with an initial setup for a Node.js app. import PrismaInitPartial from './_prisma-init-partial.mdx' --- # MongoDB URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/mongodb-typescript-mongodb Learn how to create a new Node.js or TypeScript project from scratch by connecting Prisma ORM to your MongoDB database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli) and [Prisma Client](/orm/prisma-client). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - Access to a MongoDB 4.2+ server with a replica set deployment. We recommend using [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). The MongoDB database connector uses transactions to support nested writes. Transactions **require** a [replica set](https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/) deployment. The easiest way to deploy a replica set is with [Atlas](https://www.mongodb.com/docs/atlas/getting-started/). It's free to get started. Make sure you have your database [connection URL](/orm/reference/connection-urls) at hand. If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). > See [System requirements](/orm/reference/system-requirements) for exact version requirements. ## Create project setup As a first step, create a project directory and navigate into it: ```terminal copy mkdir hello-prisma cd hello-prisma ``` Next, initialize a TypeScript project and add the Prisma CLI as a development dependency to it: ```terminal copy npm init -y npm install prisma typescript tsx @types/node --save-dev ``` This creates a `package.json` with an initial setup for your TypeScript app. Next, initialize TypeScript: ```terminal copy npx tsc --init ``` import PrismaInitPartial from './_prisma-init-partial.mdx' --- import CodeBlock from '@theme/CodeBlock'; You can now invoke the Prisma CLI by prefixing it with `npx`: ```terminal npx prisma ``` Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: {`npx prisma init --datasource-provider ${props.datasource.toLowerCase()} --output ../generated/prisma`} This command does a few things: - Creates a new directory called `prisma` that contains a file called `schema.prisma`, which contains the Prisma Schema with your database connection variable and schema models. - Sets the `datasource` to {props.datasource} and the output to a custom location, respectively. - Creates the [`.env` file](/orm/more/development-environment/environment-variables) in the root directory of the project, which is used for defining environment variables (such as your database connection) :::info Using version control? If you're using version control, like git, we recommend you add a line to your `.gitignore` in order to exclude the generated client from your application. In this example, we want to exclude the `generated/prisma` directory. ```code file=.gitignore //add-start generated/prisma/ //add-end ``` ::: Note that the default schema created by `prisma init` uses PostgreSQL as the `provider`. If you didn't specify a provider with the `datasource-provider` option, you need to edit the `datasource` block to use the {props.datasource.toLowerCase()} provider instead: {`datasource db { //edit-next-line provider = "${props.datasource.toLowerCase()}" url = env("DATABASE_URL") }`} --- # Start from scratch URL: https://www.prisma.io/docs/getting-started/setup-prisma/start-from-scratch/index Start a fresh project from scratch with the following tutorials as they introduce you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). ## In this section --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-cockroachdb ## Connecting your database To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` The `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`. You now need to adjust the connection URL to point to your own database.

Connection URL

The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. CockroachDB uses the PostgreSQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines postgresql://USER:PASSWORD@HOST:PORT/DATABASE?PARAMETERS ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `PORT`: The port where your database server is running. The default for CockroachDB is `26257`. - `DATABASE`: The name of the database - `PARAMETERS`: Any additional connection parameters. See the CockroachDB documentation [here](https://www.cockroachlabs.com/docs/stable/connection-parameters.html#additional-connection-parameters). For a [CockroachDB Serverless](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart.html) or [Cockroach Dedicated](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart-trial-cluster) database hosted on [CockroachDB Cloud](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart/), the [connection URL](/orm/reference/connection-urls) looks similar to this: ```bash file=.env DATABASE_URL="postgresql://:@..cockroachlabs.cloud:26257/defaultdb?sslmode=verify-full&sslrootcert=$HOME/.postgresql/root.crt&options=--" ``` To find your connection string on CockroachDB Cloud, click the 'Connect' button on the overview page for your database cluster, and select the 'Connection string' tab. For a [CockroachDB database hosted locally](https://www.cockroachlabs.com/docs/stable/secure-a-cluster.html), the [connection URL](/orm/reference/connection-urls) looks similar to this: ```bash file=.env DATABASE_URL="postgresql://root@localhost:26257?sslmode=disable" ``` Your connection string is displayed as part of the welcome text when starting CockroachDB from the command line. --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-mysql ## Connecting your database To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: ```bash file=.env DATABASE_URL="mysql://johndoe:randompassword@localhost:3306/mydb" ``` You now need to adjust the connection URL to point to your own database.

Connection URL

The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. For MySQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines mysql://USER:PASSWORD@HOST:PORT/DATABASE ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `PORT`: The port where your database server is running (typically `3306` for MySQL) - `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) As an example, for a MySQL database hosted on AWS RDS, the [connection URL](/orm/reference/connection-urls) might look similar to this: ```bash file=.env DATABASE_URL="mysql://johndoe:XXX@mysql–instance1.123456789012.us-east-1.rds.amazonaws.com:3306/mydb" ``` When running MySQL locally, your connection URL typically looks similar to this: ```bash file=.env DATABASE_URL="mysql://root:randompassword@localhost:3306/mydb" ``` --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-planetscale To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` You will also need to set the relation mode type to `prisma` in order to [emulate foreign key constraints](/orm/overview/databases/planetscale#option-1-emulate-relations-in-prisma-client) in the `datasource` block: ```prisma file=schema.prisma highlight=4;add showLineNumbers datasource db { provider = "mysql" url = env("DATABASE_URL") //add-next-line relationMode = "prisma" } ``` > **Note**: Since February 2024, you can alternatively [use foreign key constraints on a database-level in PlanetScale](/orm/overview/databases/planetscale#option-2-enable-foreign-key-constraints-in-the-planetscale-database-settings), which omits the need for setting `relationMode = "prisma"`. The `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: ```bash file=.env DATABASE_URL="mysql://janedoe:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" ``` You now need to adjust the connection URL to point to your own database. The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. PlanetScale uses the MySQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines mysql://USER:PASSWORD@HOST:PORT/DATABASE ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `PORT`: The port where your database server is running (typically `3306` for MySQL) - `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) For a database hosted with PlanetScale, the [connection URL](/orm/reference/connection-urls) looks similar to this: ```bash file=.env DATABASE_URL="mysql://myusername:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" ``` The connection URL for a given database branch can be found from your PlanetScale account by going to the overview page for the branch and selecting the 'Connect' dropdown. In the 'Passwords' section, generate a new password and select 'Prisma' to get the Prisma format for the connection URL.
Alternative method: connecting using the PlanetScale CLI Alternatively, you can connect to your PlanetScale database server using the [PlanetScale CLI](https://planetscale.com/docs/concepts/planetscale-environment-setup), and use a local connection URL. In this case the connection URL will look like this: ```bash file=.env DATABASE_URL="mysql://root@localhost:PORT/mydb" ``` We recommend adding `.env` to your `.gitignore` file to prevent committing your environment variables. To connect to your branch, use the following command: ```terminal pscale connect prisma-test branchname --port PORT ``` The `--port` flag can be omitted if you are using the default port `3306`.
--- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-postgresql ## Connecting your database To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`: ```bash file=.env DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" ``` You now need to adjust the connection URL to point to your own database.

Connection URL

The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For PostgreSQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA ``` > **Note**: In most cases, you can use the [`postgres://` and `postgresql:// URI scheme designators interchangeably`](https://www.postgresql.org/docs/10/libpq-connect.html#id-1.7.3.8.3.6) - however, depending on how your database is hosted, you might need to be specific. If you're unsure what to provide for the `schema` parameter for a PostgreSQL connection URL, you can probably omit it. In that case, the default schema name `public` will be used. As an example, for a PostgreSQL database hosted on Heroku, the connection URL might look similar to this: ```bash file=.env DATABASE_URL="postgresql://opnmyfngbknppm:XXX@ec2-46-137-91-216.eu-west-1.compute.amazonaws.com:5432/d50rgmkqi2ipus?schema=hello-prisma" ``` When running PostgreSQL locally on macOS, your user and password as well as the database name _typically_ correspond to the current _user_ of your OS, e.g. assuming the user is called `janedoe`: ```bash file=.env DATABASE_URL="postgresql://janedoe:janedoe@localhost:5432/janedoe?schema=hello-prisma" ``` --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-node-sqlserver ## Connecting your database To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "sqlserver" url = env("DATABASE_URL") } ``` The `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema), the following example connection URL [uses SQL authentication](/orm/overview/databases/sql-server), but there are [other ways to format your connection URL](/orm/overview/databases/sql-server) ```bash file=.env DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=sa;password=r@ndomP@$$w0rd;trustServerCertificate=true" ``` Adjust the connection URL to match your setup - see [Microsoft SQL Server connection URL](/orm/overview/databases/sql-server) for more information. > Make sure TCP/IP connections are enabled via [SQL Server Configuration Manager](https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-configuration-manager?view=sql-server-ver16&viewFallbackFrom=sql-server-ver16) to avoid `No connection could be made because the target machine actively refused it. (os error 10061)` --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-cockroachdb ## Connecting your database To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` The `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`. You now need to adjust the connection URL to point to your own database.

Connection URL

The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. CockroachDB uses the PostgreSQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines postgresql://USER:PASSWORD@HOST:PORT/DATABASE?PARAMETERS ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `PORT`: The port where your database server is running. The default for CockroachDB is `26257`. - `DATABASE`: The name of the database - `PARAMETERS`: Any additional connection parameters. See the CockroachDB documentation [here](https://www.cockroachlabs.com/docs/stable/connection-parameters.html#additional-connection-parameters). For a [CockroachDB Serverless](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart.html) or [Cockroach Dedicated](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart-trial-cluster) database hosted on [CockroachDB Cloud](https://www.cockroachlabs.com/docs/cockroachcloud/quickstart/), the [connection URL](/orm/reference/connection-urls) looks similar to this: ```bash file=.env DATABASE_URL="postgresql://:@..cockroachlabs.cloud:26257/defaultdb?sslmode=verify-full&sslrootcert=$HOME/.postgresql/root.crt&options=--" ``` To find your connection string on CockroachDB Cloud, click the 'Connect' button on the overview page for your database cluster, and select the 'Connection string' tab. For a [CockroachDB database hosted locally](https://www.cockroachlabs.com/docs/stable/secure-a-cluster.html), the [connection URL](/orm/reference/connection-urls) looks similar to this: ```bash file=.env DATABASE_URL="postgresql://root@localhost:26257?sslmode=disable" ``` Your connection string is displayed as part of the welcome text when starting CockroachDB from the command line. --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-mysql ## Connecting your database To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: ```bash file=.env DATABASE_URL="mysql://johndoe:randompassword@localhost:3306/mydb" ``` You now need to adjust the connection URL to point to your own database.

Connection URL

The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. For MySQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines mysql://USER:PASSWORD@HOST:PORT/DATABASE ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `PORT`: The port where your database server is running (typically `3306` for MySQL) - `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) As an example, for a MySQL database hosted on AWS RDS, the [connection URL](/orm/reference/connection-urls) might look similar to this: ```bash file=.env DATABASE_URL="mysql://johndoe:XXX@mysql–instance1.123456789012.us-east-1.rds.amazonaws.com:3306/mydb" ``` When running MySQL locally, your connection URL typically looks similar to this: ```bash file=.env DATABASE_URL="mysql://root:randompassword@localhost:3306/mydb" ``` --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-planetscale ## Connecting your database To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` You will also need to [set the relation mode type to `prisma`](/orm/prisma-schema/data-model/relations/relation-mode#emulate-relations-in-prisma-orm-with-the-prisma-relation-mode) in the `datasource` block: ```prisma file=schema.prisma highlight=4;add showLineNumbers datasource db { provider = "mysql" url = env("DATABASE_URL") //add-next-line relationMode = "prisma" } ``` The `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) which is defined in `.env`: ```bash file=.env DATABASE_URL="mysql://janedoe:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" ``` You now need to adjust the connection URL to point to your own database.

Connection URL

The [format of the connection URL](/orm/reference/connection-urls) for your database typically depends on the database you use. PlanetScale uses the MySQL connection URL format, which has the following structure (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines mysql://USER:PASSWORD@HOST:PORT/DATABASE ``` Here's a short explanation of each component: - `USER`: The name of your database user - `PASSWORD`: The password for your database user - `PORT`: The port where your database server is running (typically `3306` for MySQL) - `DATABASE`: The name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) For a database hosted with PlanetScale, the [connection URL](/orm/reference/connection-urls) looks similar to this: ```bash file=.env DATABASE_URL="mysql://myusername:mypassword@server.us-east-2.psdb.cloud/mydb?sslaccept=strict" ``` The connection URL for a given database branch can be found from your PlanetScale account by going to the overview page for the branch and selecting the 'Connect' dropdown. In the 'Passwords' section, generate a new password and select 'Prisma' to get the Prisma format for the connection URL.
Alternative method: connecting using the PlanetScale CLI Alternatively, you can connect to your PlanetScale database server using the [PlanetScale CLI](https://planetscale.com/docs/concepts/planetscale-environment-setup), and use a local connection URL. In this case the connection URL will look like this: ```bash file=.env DATABASE_URL="mysql://root@localhost:PORT/mydb" ``` To connect to your branch, use the following command: ```terminal pscale connect prisma-test branchname --port PORT ``` The `--port` flag can be omitted if you are using the default port `3306`.
--- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-postgresql ## Connecting your database To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`: ```bash file=.env DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public" ``` You now need to adjust the connection URL to point to your own database.

Connection URL

The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For PostgreSQL, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA ``` > **Note**: In most cases, you can use the [`postgres://` and `postgresql:// URI scheme designators interchangeably`](https://www.postgresql.org/docs/10/libpq-connect.html#id-1.7.3.8.3.6) - however, depending on how your database is hosted, you might need to be specific. If you're unsure what to provide for the `schema` parameter for a PostgreSQL connection URL, you can probably omit it. In that case, the default schema name `public` will be used. As an example, for a PostgreSQL database hosted on Heroku, the connection URL might look similar to this: ```bash file=.env DATABASE_URL="postgresql://opnmyfngbknppm:XXX@ec2-46-137-91-216.eu-west-1.compute.amazonaws.com:5432/d50rgmkqi2ipus?schema=hello-prisma" ``` When running PostgreSQL locally on macOS, your user and password as well as the database name _typically_ correspond to the current _user_ of your OS, e.g. assuming the user is called `janedoe`: ```bash file=.env DATABASE_URL="postgresql://janedoe:janedoe@localhost:5432/janedoe?schema=hello-prisma" ``` --- # Connect your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/connect-your-database-typescript-sqlserver ## Connecting your database To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "sqlserver" url = env("DATABASE_URL") } ``` The `url` is [set via an environment variable](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema), the following example connection URL [uses SQL authentication](/orm/overview/databases/sql-server), but there are [other ways to format your connection URL](/orm/overview/databases/sql-server) ```bash file=.env DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=sa;password=r@ndomP@$$w0rd;trustServerCertificate=true" ``` Adjust the connection URL to match your setup - see [Microsoft SQL Server connection URL](/orm/overview/databases/sql-server) for more information. > Make sure TCP/IP connections are enabled via [SQL Server Configuration Manager](https://learn.microsoft.com/en-us/sql/relational-databases/sql-server-configuration-manager?view=sql-server-ver16&viewFallbackFrom=sql-server-ver16) to avoid `No connection could be made because the target machine actively refused it. (os error 10061)` --- # Introspection URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-cockroachdb ## Introspect your database with Prisma ORM For the purpose of this guide, we'll use a demo SQL schema with three tables: ```sql no-lines CREATE TABLE "User" ( id INT8 PRIMARY KEY DEFAULT unique_rowid(), name STRING(255), email STRING(255) UNIQUE NOT NULL ); CREATE TABLE "Post" ( id INT8 PRIMARY KEY DEFAULT unique_rowid(), title STRING(255) UNIQUE NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), content STRING, published BOOLEAN NOT NULL DEFAULT false, "authorId" INT8 NOT NULL, FOREIGN KEY ("authorId") REFERENCES "User"(id) ); CREATE TABLE "Profile" ( id INT8 PRIMARY KEY DEFAULT unique_rowid(), bio STRING, "userId" INT8 UNIQUE NOT NULL, FOREIGN KEY ("userId") REFERENCES "User"(id) ); ``` > **Note**: Some fields are written in double quotes to ensure CockroachDB uses proper casing. If no double-quotes were used, CockroachDB would just read everything as _lowercase_ characters.
Expand for a graphical overview of the tables **User** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------ | :---------- | :---------- | :------- | :----------------- | | `id` | `INT8` | **✔️** | No | **✔️** | _autoincrementing_ | | `name` | `STRING(255)` | No | No | No | - | | `email` | `STRING(255)` | No | No | **✔️** | - | **Post** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------ | :---------- | :---------- | :------- | :----------------- | | `id` | `INT8` | **✔️** | No | **✔️** | _autoincrementing_ | | `createdAt` | `TIMESTAMP` | No | No | **✔️** | `now()` | | `title` | `STRING(255)` | No | No | **✔️** | - | | `content` | `STRING` | No | No | No | - | | `published` | `BOOLEAN` | No | No | **✔️** | `false` | | `authorId` | `INT8` | No | **✔️** | **✔️** | - | **Profile** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INT8` | **✔️** | No | **✔️** | _autoincrementing_ | | `bio` | `STRING` | No | No | No | - | | `userId` | `INT8` | No | **✔️** | **✔️** | - |
As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. Run the following command to introspect your database: ```terminal copy npx prisma db pull ``` This command reads the environment variable used to define the `url` in your `schema.prisma`, `DATABASE_URL`, that in our case is set in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. After the introspection is complete, your Prisma schema is updated: ![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) The data model now looks similar to this: ```prisma file=prisma/schema.prisma showLineNumbers model Post { id BigInt @id @default(autoincrement()) title String @unique @db.String(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId BigInt User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model Profile { id BigInt @id @default(autoincrement()) bio String? userId BigInt @unique User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model User { id BigInt @id @default(autoincrement()) name String? @db.String(255) email String @unique @db.String(255) Post Post[] Profile Profile? } ``` Prisma ORM's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. Right now, there's a few minor "issues" with the data model: - The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. - The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. - Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: ```prisma file=prisma/schema.prisma highlight=8,15,22,23;edit showLineNumbers model Post { id BigInt @id @default(autoincrement()) title String @unique @db.String(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId BigInt //edit-next-line author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model Profile { id BigInt @id @default(autoincrement()) bio String? userId BigInt @unique //edit-next-line user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model User { id BigInt @id @default(autoincrement()) name String? @db.String(255) email String @unique @db.String(255) //edit-start posts Post[] profile Profile? //edit-end } ``` In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API.
Using custom model and field names Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. Assume you obtained the following model from introspection that's based on _snake_case_ notation: ```prisma no-lines model my_user { user_id Int @id @default(sequence()) first_name String? last_name String @unique } ``` If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: ```ts no-lines const user = await prisma.my_user.create({ data: { first_name: 'Alice', last_name: 'Smith', }, }) ``` If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): ```prisma no-lines model MyUser { userId Int @id @default(sequence()) @map("user_id") firstName String? @map("first_name") lastName String @unique @map("last_name") @@map("my_user") } ``` With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: ```ts no-lines const user = await prisma.myUser.create({ data: { firstName: 'Alice', lastName: 'Smith', }, }) ``` Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page.
--- # Introspection URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-mysql ## Introspect your database with Prisma ORM For the purpose of this guide, we'll use a demo SQL schema with three tables: ```sql no-lines CREATE TABLE User ( id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, name VARCHAR(255), email VARCHAR(255) UNIQUE NOT NULL ); CREATE TABLE Post ( id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, title VARCHAR(255) NOT NULL, createdAt TIMESTAMP NOT NULL DEFAULT now(), content TEXT, published BOOLEAN NOT NULL DEFAULT false, authorId INTEGER NOT NULL, FOREIGN KEY (authorId) REFERENCES User(id) ); CREATE TABLE Profile ( id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, bio TEXT, userId INTEGER UNIQUE NOT NULL, FOREIGN KEY (userId) REFERENCES User(id) ); ```
Expand for a graphical overview of the tables **User** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INTEGER` | **✔️** | No | **✔️** | _autoincrementing_ | | `name` | `VARCHAR(255)` | No | No | No | - | | `email` | `VARCHAR(255)` | No | No | **✔️** | - | **Post** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INTEGER` | **✔️** | No | **✔️** | _autoincrementing_ | | `createdAt` | `DATETIME(3)` | No | No | **✔️** | `now()` | | `title` | `VARCHAR(255)` | No | No | **✔️** | - | | `content` | `TEXT` | No | No | No | - | | `published` | `BOOLEAN` | No | No | **✔️** | `false` | | `authorId` | `INTEGER` | No | **✔️** | **✔️** | `false` | **Profile** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :-------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INTEGER` | **✔️** | No | **✔️** | _autoincrementing_ | | `bio` | `TEXT` | No | No | No | - | | `userId` | `INTEGER` | No | **✔️** | **✔️** | - |
As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. Run the following command to introspect your database: ```terminal copy npx prisma db pull ``` This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. After the introspection is complete, your Prisma schema is updated: ![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) The data model now looks similar to this (note that the fields on the models have been reordered for better readability): ```prisma file=prisma/schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(0) content String? @db.Text published Boolean @default(false) authorId Int User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Post_ibfk_1") @@index([authorId], map: "authorId") } model Profile { id Int @id @default(autoincrement()) bio String? @db.Text userId Int @unique(map: "userId") User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Profile_ibfk_1") } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique(map: "email") @db.VarChar(255) Post Post[] Profile Profile? } ``` :::info Refer to the [Prisma schema reference](/orm/reference/prisma-schema-reference) for detailed information about the schema definition. ::: Prisma ORM's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. Right now, there's a few minor "issues" with the data model: - The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. - The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. - Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: ```prisma file=prisma/schema.prisma highlight=8,17,24,25;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(0) content String? @db.Text published Boolean @default(false) authorId Int //edit-next-line author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Post_ibfk_1") @@index([authorId], map: "authorId") } model Profile { id Int @id @default(autoincrement()) bio String? @db.Text userId Int @unique(map: "userId") //edit-next-line user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Profile_ibfk_1") } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique(map: "email") @db.VarChar(255) //edit-start posts Post[] profile Profile? //edit-end } ``` In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API. Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. Assume you obtained the following model from introspection that's based on _snake_case_ notation: ```prisma no-lines model my_user { user_id Int @id @default(autoincrement()) first_name String? last_name String @unique } ``` If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: ```ts no-lines const user = await prisma.my_user.create({ data: { first_name: 'Alice', last_name: 'Smith', }, }) ``` If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): ```prisma no-lines model MyUser { userId Int @id @default(autoincrement()) @map("user_id") firstName String? @map("first_name") lastName String @unique @map("last_name") @@map("my_user") } ``` With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: ```ts no-lines const user = await prisma.myUser.create({ data: { firstName: 'Alice', lastName: 'Smith', }, }) ``` Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page. --- # Introspection URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-planetscale ## Introspect your database with Prisma ORM For the purpose of this guide, we'll use a demo SQL schema with three tables: ```sql no-lines CREATE TABLE `Post` ( `id` int NOT NULL AUTO_INCREMENT, `createdAt` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `updatedAt` datetime(3) NOT NULL, `title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `content` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `published` tinyint(1) NOT NULL DEFAULT '0', `authorId` int NOT NULL, PRIMARY KEY (`id`), KEY `Post_authorId_idx` (`authorId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE `Profile` ( `id` int NOT NULL AUTO_INCREMENT, `bio` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `userId` int NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `Profile_userId_key` (`userId`), KEY `Profile_userId_idx` (`userId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE `User` ( `id` int NOT NULL AUTO_INCREMENT, `email` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL, `name` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `User_email_key` (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ```
Expand for a graphical overview of the tables **Post** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `int` | **✔️** | No | **✔️** | _autoincrementing_ | | `createdAt` | `datetime(3)` | No | No | **✔️** | `now()` | | `updatedAt` | `datetime(3)` | No | No | **✔️** | | | `title` | `varchar(255)` | No | No | **✔️** | - | | `content` | `varchar(191)` | No | No | No | - | | `published` | `tinyint(1)` | No | No | **✔️** | `false` | | `authorId` | `int` | No | No | **✔️** | - | **Profile** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `int` | **✔️** | No | **✔️** | _autoincrementing_ | | `bio` | `varchar(191)` | No | No | No | - | | `userId` | `int` | No | No | **✔️** | - | **User** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `int` | **✔️** | No | **✔️** | _autoincrementing_ | | `name` | `varchar(191)` | No | No | No | - | | `email` | `varchar(191)` | No | No | **✔️** | - |
As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. Run the following command to introspect your database: ```terminal copy npx prisma db pull ``` This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. After the introspection is complete, your Prisma schema is updated: ![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) The data model now looks similar to this: ```prisma file=prisma/schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime title String @db.VarChar(255) content String? published Boolean @default(false) authorId Int @@index([authorId]) } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique @@index([userId]) } model User { id Int @id @default(autoincrement()) email String @unique name String? } ``` :::info Refer to the [Prisma schema reference](/orm/reference/prisma-schema-reference) for detailed information about the schema definition. ::: Prisma's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. You will then need to add in any missing relations between your data using [relation fields](/orm/prisma-schema/data-model/relations#relation-fields): ```prisma file=prisma/schema.prisma highlight=8,17,27,28;add showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime title String @db.VarChar(255) content String? published Boolean @default(false) //add-next-line author User @relation(fields: [authorId], references: [id]) authorId Int @@index([authorId]) } model Profile { id Int @id @default(autoincrement()) bio String? //add-next-line user User @relation(fields: [userId], references: [id]) userId Int @unique @@index([userId]) } model User { id Int @id @default(autoincrement()) email String @unique name String? //add-start posts Post[] profile Profile? //add-end } ``` After this, run introspection on your database for a second time: ```terminal copy npx prisma db pull ``` Prisma Migrate will now keep the manually added relation fields. Because relation fields are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database. In this example, the database schema follows the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models. This optimizes the ergonomics of the generated Prisma Client API.
Using custom model and field names Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. Assume you obtained the following model from introspection that's based on _snake_case_ notation: ```prisma no-lines model my_user { user_id Int @id @default(autoincrement()) first_name String? last_name String @unique } ``` If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: ```ts no-lines const user = await prisma.my_user.create({ data: { first_name: 'Alice', last_name: 'Smith', }, }) ``` If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): ```prisma no-lines model MyUser { userId Int @id @default(autoincrement()) @map("user_id") firstName String? @map("first_name") lastName String @unique @map("last_name") @@map("my_user") } ``` With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: ```ts no-lines const user = await prisma.myUser.create({ data: { firstName: 'Alice', lastName: 'Smith', }, }) ``` Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page.
--- # Introspection URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-postgresql ## Introspect your database with Prisma ORM For the purpose of this guide, we'll use a demo SQL schema with three tables: ```sql no-lines CREATE TABLE "public"."User" ( id SERIAL PRIMARY KEY NOT NULL, name VARCHAR(255), email VARCHAR(255) UNIQUE NOT NULL ); CREATE TABLE "public"."Post" ( id SERIAL PRIMARY KEY NOT NULL, title VARCHAR(255) NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), content TEXT, published BOOLEAN NOT NULL DEFAULT false, "authorId" INTEGER NOT NULL, FOREIGN KEY ("authorId") REFERENCES "public"."User"(id) ); CREATE TABLE "public"."Profile" ( id SERIAL PRIMARY KEY NOT NULL, bio TEXT, "userId" INTEGER UNIQUE NOT NULL, FOREIGN KEY ("userId") REFERENCES "public"."User"(id) ); ``` > **Note**: Some fields are written in double-quotes to ensure PostgreSQL uses proper casing. If no double-quotes were used, PostgreSQL would just read everything as _lowercase_ characters.
Expand for a graphical overview of the tables **User** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `SERIAL` | **✔️** | No | **✔️** | _autoincrementing_ | | `name` | `VARCHAR(255)` | No | No | No | - | | `email` | `VARCHAR(255)` | No | No | **✔️** | - | **Post** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `SERIAL` | **✔️** | No | **✔️** | _autoincrementing_ | | `createdAt` | `TIMESTAMP` | No | No | **✔️** | `now()` | | `title` | `VARCHAR(255)` | No | No | **✔️** | - | | `content` | `TEXT` | No | No | No | - | | `published` | `BOOLEAN` | No | No | **✔️** | `false` | | `authorId` | `INTEGER` | No | **✔️** | **✔️** | - | **Profile** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :-------- | :---------- | :---------- | :------- | :----------------- | | `id` | `SERIAL` | **✔️** | No | **✔️** | _autoincrementing_ | | `bio` | `TEXT` | No | No | No | - | | `userId` | `INTEGER` | No | **✔️** | **✔️** | - |
As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. Run the following command to introspect your database: ```terminal copy npx prisma db pull ``` This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a data model in your Prisma schema. After the introspection is complete, your Prisma schema is updated: ![Introspect your database with Prisma ORM](/img/getting-started/prisma-db-pull-generate-schema.png) The data model now looks similar to this (note that the fields on the models have been reordered for better readability): ```prisma file=prisma/schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) Post Post[] Profile Profile? } ``` Prisma ORM's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. Right now, there's a few minor "issues" with the data model: - The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. - The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. - Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: ```prisma file=prisma/schema.prisma highlight=8,15,22,23;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int //edit-next-line author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique //edit-next-line user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) //edit-start posts Post[] profile Profile? //edit-end } ``` In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API.
Using custom model and field names Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. Assume you obtained the following model from introspection that's based on _snake_case_ notation: ```prisma no-lines model my_user { user_id Int @id @default(autoincrement()) first_name String? last_name String @unique } ``` If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: ```ts no-lines const user = await prisma.my_user.create({ data: { first_name: 'Alice', last_name: 'Smith', }, }) ``` If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): ```prisma no-lines model MyUser { userId Int @id @default(autoincrement()) @map("user_id") firstName String? @map("first_name") lastName String @unique @map("last_name") @@map("my_user") } ``` With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: ```ts no-lines const user = await prisma.myUser.create({ data: { firstName: 'Alice', lastName: 'Smith', }, }) ``` Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page.
--- # Introspection URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-node-sqlserver ## Introspect your database with Prisma ORM For the purpose of this guide, we'll use a demo SQL schema with three tables: ```sql no-lines CREATE TABLE [dbo].[Post] ( [id] INT NOT NULL IDENTITY(1,1), [createdAt] DATETIME2 NOT NULL CONSTRAINT [Post_createdAt_df] DEFAULT CURRENT_TIMESTAMP, [updatedAt] DATETIME2 NOT NULL, [title] VARCHAR(255) NOT NULL, [content] NVARCHAR(1000), [published] BIT NOT NULL CONSTRAINT [Post_published_df] DEFAULT 0, [authorId] INT NOT NULL, CONSTRAINT [Post_pkey] PRIMARY KEY ([id]) ); CREATE TABLE [dbo].[Profile] ( [id] INT NOT NULL IDENTITY(1,1), [bio] NVARCHAR(1000), [userId] INT NOT NULL, CONSTRAINT [Profile_pkey] PRIMARY KEY ([id]), CONSTRAINT [Profile_userId_key] UNIQUE ([userId]) ); CREATE TABLE [dbo].[User] ( [id] INT NOT NULL IDENTITY(1,1), [email] NVARCHAR(1000) NOT NULL, [name] NVARCHAR(1000), CONSTRAINT [User_pkey] PRIMARY KEY ([id]), CONSTRAINT [User_email_key] UNIQUE ([email]) ); ALTER TABLE [dbo].[Post] ADD CONSTRAINT [Post_authorId_fkey] FOREIGN KEY ([authorId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; ALTER TABLE [dbo].[Profile] ADD CONSTRAINT [Profile_userId_fkey] FOREIGN KEY ([userId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; ```
Expand for a graphical overview of the tables **User** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :--------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INT` | **✔️** | No | **✔️** | _autoincrementing_ | | `name` | `NVARCHAR(1000)` | No | No | No | - | | `email` | `NVARCHAR(1000)` | No | No | **✔️** | - | **Post** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :--------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INT` | **✔️** | No | **✔️** | _autoincrementing_ | | `createdAt` | `DATETIME2` | No | No | **✔️** | `now()` | | `updatedAt` | `DATETIME2` | No | No | **✔️** | | | `title` | `VARCHAR(255)` | No | No | **✔️** | - | | `content` | `NVARCHAR(1000)` | No | No | No | - | | `published` | `BIT` | No | No | **✔️** | `false` | | `authorId` | `INT` | No | **✔️** | **✔️** | - | **Profile** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :--------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INT` | **✔️** | No | **✔️** | _autoincrementing_ | | `bio` | `NVARCHAR(1000)` | No | No | No | - | | `userId` | `INT` | No | **✔️** | **✔️** | - |
As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. Run the following command to introspect your database: ```terminal copy npx prisma db pull ``` This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. After the introspection is complete, your Prisma schema is updated: ![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) The data model now looks similar to this (note that the fields on the models have been reordered for better readability): ```prisma file=prisma/schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int User User @relation(fields: [authorId], references: [id]) } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique User User @relation(fields: [userId], references: [id]) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) Post Post[] Profile Profile? } ``` Prisma's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. Right now, there's a few minor "issues" with the data model: - The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. - The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. - Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: ```prisma file=prisma/schema.prisma highlight=7,14,22,23;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) //edit-next-line author User @relation(fields: [authorId], references: [id]) authorId Int } model Profile { id Int @id @default(autoincrement()) bio String? //edit-next-line user User @relation(fields: [userId], references: [id]) userId Int @unique } model User { id Int @id @default(autoincrement()) email String @unique @db.VarChar(255) name String? @db.VarChar(255) //edit-start posts Post[] profile Profile? //edit-end } ``` In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API.
Using custom model and field names Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. Assume you obtained the following model from introspection that's based on _snake_case_ notation: ```prisma no-lines model my_user { user_id Int @id @default(autoincrement()) first_name String? last_name String @unique } ``` If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: ```ts no-lines const user = await prisma.my_user.create({ data: { first_name: 'Alice', last_name: 'Smith', }, }) ``` If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): ```prisma no-lines model MyUser { userId Int @id @default(autoincrement()) @map("user_id") firstName String? @map("first_name") lastName String @unique @map("last_name") @@map("my_user") } ``` With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: ```ts no-lines const user = await prisma.myUser.create({ data: { firstName: 'Alice', lastName: 'Smith', }, }) ``` Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page.
--- # Introspection URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-cockroachdb ## Introspect your database with Prisma ORM For the purpose of this guide, we'll use a demo SQL schema with three tables: ```sql no-lines CREATE TABLE "User" ( id INT8 PRIMARY KEY DEFAULT unique_rowid(), name STRING(255), email STRING(255) UNIQUE NOT NULL ); CREATE TABLE "Post" ( id INT8 PRIMARY KEY DEFAULT unique_rowid(), title STRING(255) UNIQUE NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), content STRING, published BOOLEAN NOT NULL DEFAULT false, "authorId" INT8 NOT NULL, FOREIGN KEY ("authorId") REFERENCES "User"(id) ); CREATE TABLE "Profile" ( id INT8 PRIMARY KEY DEFAULT unique_rowid(), bio STRING, "userId" INT8 UNIQUE NOT NULL, FOREIGN KEY ("userId") REFERENCES "User"(id) ); ``` > **Note**: Some fields are written in double quotes to ensure CockroachDB uses proper casing. If no double-quotes were used, CockroachDB would just read everything as _lowercase_ characters.
Expand for a graphical overview of the tables **User** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------ | :---------- | :---------- | :------- | :----------------- | | `id` | `INT8` | **✔️** | No | **✔️** | _autoincrementing_ | | `name` | `STRING(255)` | No | No | No | - | | `email` | `STRING(255)` | No | No | **✔️** | - | **Post** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------ | :---------- | :---------- | :------- | :----------------- | | `id` | `INT8` | **✔️** | No | **✔️** | _autoincrementing_ | | `createdAt` | `TIMESTAMP` | No | No | **✔️** | `now()` | | `title` | `STRING(255)` | No | No | **✔️** | - | | `content` | `STRING` | No | No | No | - | | `published` | `BOOLEAN` | No | No | **✔️** | `false` | | `authorId` | `INT8` | No | **✔️** | **✔️** | - | **Profile** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INT8` | **✔️** | No | **✔️** | _autoincrementing_ | | `bio` | `STRING` | No | No | No | - | | `userId` | `INT8` | No | **✔️** | **✔️** | - |
As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. Run the following command to introspect your database: ```terminal copy npx prisma db pull ``` This command reads the environment variable used to define the `url` in your `schema.prisma`, `DATABASE_URL`, that in our case is set in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. After the introspection is complete, your Prisma schema is updated: ![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) The data model now looks similar to this: ```prisma file=prisma/schema.prisma showLineNumbers model Post { id BigInt @id @default(autoincrement()) title String @unique @db.String(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId BigInt User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model Profile { id BigInt @id @default(autoincrement()) bio String? userId BigInt @unique User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model User { id BigInt @id @default(autoincrement()) name String? @db.String(255) email String @unique @db.String(255) Post Post[] Profile Profile? } ``` Prisma ORM's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. Right now, there's a few minor "issues" with the data model: - The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. - The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. - Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: ```prisma file=prisma/schema.prisma highlight=8,15,22,23;edit showLineNumbers model Post { id BigInt @id @default(autoincrement()) title String @unique @db.String(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId BigInt //edit-next-line author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model Profile { id BigInt @id @default(autoincrement()) bio String? userId BigInt @unique //edit-next-line user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model User { id BigInt @id @default(autoincrement()) name String? @db.String(255) email String @unique @db.String(255) //edit-start posts Post[] profile Profile? //edit-end } ``` In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API.
Using custom model and field names Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. Assume you obtained the following model from introspection that's based on _snake_case_ notation: ```prisma no-lines model my_user { user_id Int @id @default(sequence()) first_name String? last_name String @unique } ``` If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: ```ts no-lines const user = await prisma.my_user.create({ data: { first_name: 'Alice', last_name: 'Smith', }, }) ``` If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): ```prisma no-lines model MyUser { userId Int @id @default(sequence()) @map("user_id") firstName String? @map("first_name") lastName String @unique @map("last_name") @@map("my_user") } ``` With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: ```ts no-lines const user = await prisma.myUser.create({ data: { firstName: 'Alice', lastName: 'Smith', }, }) ``` Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page.
--- # Introspection URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-mysql ## Introspect your database with Prisma ORM For the purpose of this guide, we'll use a demo SQL schema with three tables: ```sql no-lines CREATE TABLE User ( id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, name VARCHAR(255), email VARCHAR(255) UNIQUE NOT NULL ); CREATE TABLE Post ( id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, title VARCHAR(255) NOT NULL, createdAt TIMESTAMP NOT NULL DEFAULT now(), content TEXT, published BOOLEAN NOT NULL DEFAULT false, authorId INTEGER NOT NULL, FOREIGN KEY (authorId) REFERENCES User(id) ); CREATE TABLE Profile ( id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL, bio TEXT, userId INTEGER UNIQUE NOT NULL, FOREIGN KEY (userId) REFERENCES User(id) ); ```
Expand for a graphical overview of the tables **User** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INTEGER` | **✔️** | No | **✔️** | _autoincrementing_ | | `name` | `VARCHAR(255)` | No | No | No | - | | `email` | `VARCHAR(255)` | No | No | **✔️** | - | **Post** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INTEGER` | **✔️** | No | **✔️** | _autoincrementing_ | | `createdAt` | `DATETIME(3)` | No | No | **✔️** | `now()` | | `title` | `VARCHAR(255)` | No | No | **✔️** | - | | `content` | `TEXT` | No | No | No | - | | `published` | `BOOLEAN` | No | No | **✔️** | `false` | | `authorId` | `INTEGER` | No | **✔️** | **✔️** | `false` | **Profile** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :-------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INTEGER` | **✔️** | No | **✔️** | _autoincrementing_ | | `bio` | `TEXT` | No | No | No | - | | `userId` | `INTEGER` | No | **✔️** | **✔️** | - |
As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. Run the following command to introspect your database: ```terminal copy npx prisma db pull ``` This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. After the introspection is complete, your Prisma schema is updated: ![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) The data model now looks similar to this (note that the fields on the models have been reordered for better readability): ```prisma file=prisma/schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(0) content String? @db.Text published Boolean @default(false) authorId Int User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Post_ibfk_1") @@index([authorId], map: "authorId") } model Profile { id Int @id @default(autoincrement()) bio String? @db.Text userId Int @unique(map: "userId") User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Profile_ibfk_1") } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique(map: "email") @db.VarChar(255) Post Post[] Profile Profile? } ``` :::info Refer to the [Prisma schema reference](/orm/reference/prisma-schema-reference) for detailed information about the schema definition. ::: Prisma ORM's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. Right now, there's a few minor "issues" with the data model: - The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. - The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. - Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: ```prisma file=prisma/schema.prisma highlight=8,17,24,25;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(0) content String? @db.Text published Boolean @default(false) authorId Int //edit-next-line author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Post_ibfk_1") @@index([authorId], map: "authorId") } model Profile { id Int @id @default(autoincrement()) bio String? @db.Text userId Int @unique(map: "userId") //edit-next-line user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Profile_ibfk_1") } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique(map: "email") @db.VarChar(255) //edit-start posts Post[] profile Profile? //edit-end } ``` In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API. Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. Assume you obtained the following model from introspection that's based on _snake_case_ notation: ```prisma no-lines model my_user { user_id Int @id @default(autoincrement()) first_name String? last_name String @unique } ``` If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: ```ts no-lines const user = await prisma.my_user.create({ data: { first_name: 'Alice', last_name: 'Smith', }, }) ``` If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): ```prisma no-lines model MyUser { userId Int @id @default(autoincrement()) @map("user_id") firstName String? @map("first_name") lastName String @unique @map("last_name") @@map("my_user") } ``` With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: ```ts no-lines const user = await prisma.myUser.create({ data: { firstName: 'Alice', lastName: 'Smith', }, }) ``` Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page. --- # Introspection URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-planetscale ## Introspect your database with Prisma ORM For the purpose of this guide, we'll use a demo SQL schema with three tables: ```sql no-lines CREATE TABLE `Post` ( `id` int NOT NULL AUTO_INCREMENT, `createdAt` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), `updatedAt` datetime(3) NOT NULL, `title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL, `content` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `published` tinyint(1) NOT NULL DEFAULT '0', `authorId` int NOT NULL, PRIMARY KEY (`id`), KEY `Post_authorId_idx` (`authorId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE `Profile` ( `id` int NOT NULL AUTO_INCREMENT, `bio` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, `userId` int NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `Profile_userId_key` (`userId`), KEY `Profile_userId_idx` (`userId`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; CREATE TABLE `User` ( `id` int NOT NULL AUTO_INCREMENT, `email` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL, `name` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY `User_email_key` (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ```
Expand for a graphical overview of the tables **Post** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `int` | **✔️** | No | **✔️** | _autoincrementing_ | | `createdAt` | `datetime(3)` | No | No | **✔️** | `now()` | | `updatedAt` | `datetime(3)` | No | No | **✔️** | | | `title` | `varchar(255)` | No | No | **✔️** | - | | `content` | `varchar(191)` | No | No | No | - | | `published` | `tinyint(1)` | No | No | **✔️** | `false` | | `authorId` | `int` | No | No | **✔️** | - | **Profile** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `int` | **✔️** | No | **✔️** | _autoincrementing_ | | `bio` | `varchar(191)` | No | No | No | - | | `userId` | `int` | No | No | **✔️** | - | **User** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `int` | **✔️** | No | **✔️** | _autoincrementing_ | | `name` | `varchar(191)` | No | No | No | - | | `email` | `varchar(191)` | No | No | **✔️** | - |
As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. Run the following command to introspect your database: ```terminal copy npx prisma db pull ``` This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. After the introspection is complete, your Prisma schema is updated: ![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) The data model now looks similar to this: ```prisma file=prisma/schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime title String @db.VarChar(255) content String? published Boolean @default(false) authorId Int @@index([authorId]) } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique @@index([userId]) } model User { id Int @id @default(autoincrement()) email String @unique name String? } ``` :::info Refer to the [Prisma schema reference](/orm/reference/prisma-schema-reference) for detailed information about the schema definition. ::: Prisma's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. You will then need to add in any missing relations between your data using [relation fields](/orm/prisma-schema/data-model/relations#relation-fields): ```prisma file=prisma/schema.prisma highlight=8,17,27,28;add showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime title String @db.VarChar(255) content String? published Boolean @default(false) //add-next-line author User @relation(fields: [authorId], references: [id]) authorId Int @@index([authorId]) } model Profile { id Int @id @default(autoincrement()) bio String? //add-next-line user User @relation(fields: [userId], references: [id]) userId Int @unique @@index([userId]) } model User { id Int @id @default(autoincrement()) email String @unique name String? //add-start posts Post[] profile Profile? //add-end } ``` After this, run introspection on your database for a second time: ```terminal copy npx prisma db pull ``` Prisma Migrate will now keep the manually added relation fields. Because relation fields are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database. In this example, the database schema follows the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models. This optimizes the ergonomics of the generated Prisma Client API.
Using custom model and field names Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. Assume you obtained the following model from introspection that's based on _snake_case_ notation: ```prisma no-lines model my_user { user_id Int @id @default(autoincrement()) first_name String? last_name String @unique } ``` If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: ```ts no-lines const user = await prisma.my_user.create({ data: { first_name: 'Alice', last_name: 'Smith', }, }) ``` If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): ```prisma no-lines model MyUser { userId Int @id @default(autoincrement()) @map("user_id") firstName String? @map("first_name") lastName String @unique @map("last_name") @@map("my_user") } ``` With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: ```ts no-lines const user = await prisma.myUser.create({ data: { firstName: 'Alice', lastName: 'Smith', }, }) ``` Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page.
--- # Introspection URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-postgresql ## Introspect your database with Prisma ORM For the purpose of this guide, we'll use a demo SQL schema with three tables: ```sql no-lines CREATE TABLE "public"."User" ( id SERIAL PRIMARY KEY NOT NULL, name VARCHAR(255), email VARCHAR(255) UNIQUE NOT NULL ); CREATE TABLE "public"."Post" ( id SERIAL PRIMARY KEY NOT NULL, title VARCHAR(255) NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), content TEXT, published BOOLEAN NOT NULL DEFAULT false, "authorId" INTEGER NOT NULL, FOREIGN KEY ("authorId") REFERENCES "public"."User"(id) ); CREATE TABLE "public"."Profile" ( id SERIAL PRIMARY KEY NOT NULL, bio TEXT, "userId" INTEGER UNIQUE NOT NULL, FOREIGN KEY ("userId") REFERENCES "public"."User"(id) ); ``` > **Note**: Some fields are written in double-quotes to ensure PostgreSQL uses proper casing. If no double-quotes were used, PostgreSQL would just read everything as _lowercase_ characters.
Expand for a graphical overview of the tables **User** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `SERIAL` | **✔️** | No | **✔️** | _autoincrementing_ | | `name` | `VARCHAR(255)` | No | No | No | - | | `email` | `VARCHAR(255)` | No | No | **✔️** | - | **Post** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `SERIAL` | **✔️** | No | **✔️** | _autoincrementing_ | | `createdAt` | `TIMESTAMP` | No | No | **✔️** | `now()` | | `title` | `VARCHAR(255)` | No | No | **✔️** | - | | `content` | `TEXT` | No | No | No | - | | `published` | `BOOLEAN` | No | No | **✔️** | `false` | | `authorId` | `INTEGER` | No | **✔️** | **✔️** | - | **Profile** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :-------- | :---------- | :---------- | :------- | :----------------- | | `id` | `SERIAL` | **✔️** | No | **✔️** | _autoincrementing_ | | `bio` | `TEXT` | No | No | No | - | | `userId` | `INTEGER` | No | **✔️** | **✔️** | - |
As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. Run the following command to introspect your database: ```terminal copy npx prisma db pull ``` This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a data model in your Prisma schema. After the introspection is complete, your Prisma schema is updated: ![Introspect your database with Prisma ORM](/img/getting-started/prisma-db-pull-generate-schema.png) The data model now looks similar to this (note that the fields on the models have been reordered for better readability): ```prisma file=prisma/schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) Post Post[] Profile Profile? } ``` Prisma ORM's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. Right now, there's a few minor "issues" with the data model: - The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. - The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. - Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: ```prisma file=prisma/schema.prisma highlight=8,15,22,23;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int //edit-next-line author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique //edit-next-line user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) //edit-start posts Post[] profile Profile? //edit-end } ``` In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API.
Using custom model and field names Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. Assume you obtained the following model from introspection that's based on _snake_case_ notation: ```prisma no-lines model my_user { user_id Int @id @default(autoincrement()) first_name String? last_name String @unique } ``` If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: ```ts no-lines const user = await prisma.my_user.create({ data: { first_name: 'Alice', last_name: 'Smith', }, }) ``` If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): ```prisma no-lines model MyUser { userId Int @id @default(autoincrement()) @map("user_id") firstName String? @map("first_name") lastName String @unique @map("last_name") @@map("my_user") } ``` With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: ```ts no-lines const user = await prisma.myUser.create({ data: { firstName: 'Alice', lastName: 'Smith', }, }) ``` Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page.
--- # Introspection URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-sqlserver ## Introspect your database with Prisma ORM For the purpose of this guide, we'll use a demo SQL schema with three tables: ```sql no-lines CREATE TABLE [dbo].[Post] ( [id] INT NOT NULL IDENTITY(1,1), [createdAt] DATETIME2 NOT NULL CONSTRAINT [Post_createdAt_df] DEFAULT CURRENT_TIMESTAMP, [updatedAt] DATETIME2 NOT NULL, [title] VARCHAR(255) NOT NULL, [content] NVARCHAR(1000), [published] BIT NOT NULL CONSTRAINT [Post_published_df] DEFAULT 0, [authorId] INT NOT NULL, CONSTRAINT [Post_pkey] PRIMARY KEY ([id]) ); CREATE TABLE [dbo].[Profile] ( [id] INT NOT NULL IDENTITY(1,1), [bio] NVARCHAR(1000), [userId] INT NOT NULL, CONSTRAINT [Profile_pkey] PRIMARY KEY ([id]), CONSTRAINT [Profile_userId_key] UNIQUE ([userId]) ); CREATE TABLE [dbo].[User] ( [id] INT NOT NULL IDENTITY(1,1), [email] NVARCHAR(1000) NOT NULL, [name] NVARCHAR(1000), CONSTRAINT [User_pkey] PRIMARY KEY ([id]), CONSTRAINT [User_email_key] UNIQUE ([email]) ); ALTER TABLE [dbo].[Post] ADD CONSTRAINT [Post_authorId_fkey] FOREIGN KEY ([authorId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; ALTER TABLE [dbo].[Profile] ADD CONSTRAINT [Profile_userId_fkey] FOREIGN KEY ([userId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; ```
Expand for a graphical overview of the tables **User** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :--------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INT` | **✔️** | No | **✔️** | _autoincrementing_ | | `name` | `NVARCHAR(1000)` | No | No | No | - | | `email` | `NVARCHAR(1000)` | No | No | **✔️** | - | **Post** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :--------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INT` | **✔️** | No | **✔️** | _autoincrementing_ | | `createdAt` | `DATETIME2` | No | No | **✔️** | `now()` | | `updatedAt` | `DATETIME2` | No | No | **✔️** | | | `title` | `VARCHAR(255)` | No | No | **✔️** | - | | `content` | `NVARCHAR(1000)` | No | No | No | - | | `published` | `BIT` | No | No | **✔️** | `false` | | `authorId` | `INT` | No | **✔️** | **✔️** | - | **Profile** | Column name | Type | Primary key | Foreign key | Required | Default | | :---------- | :--------------- | :---------- | :---------- | :------- | :----------------- | | `id` | `INT` | **✔️** | No | **✔️** | _autoincrementing_ | | `bio` | `NVARCHAR(1000)` | No | No | No | - | | `userId` | `INT` | No | **✔️** | **✔️** | - |
As a next step, you will introspect your database. The result of the introspection will be a [data model](/orm/prisma-schema/data-model/models) inside your Prisma schema. Run the following command to introspect your database: ```terminal copy npx prisma db pull ``` This command reads the `DATABASE_URL` environment variable that's defined in `.env` and connects to your database. Once the connection is established, it introspects the database (i.e. it _reads the database schema_). It then translates the database schema from SQL into a Prisma data model. After the introspection is complete, your Prisma schema is updated: ![Introspect your database](/img/getting-started/prisma-db-pull-generate-schema.png) The data model now looks similar to this (note that the fields on the models have been reordered for better readability): ```prisma file=prisma/schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int User User @relation(fields: [authorId], references: [id]) } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique User User @relation(fields: [userId], references: [id]) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) Post Post[] Profile Profile? } ``` Prisma's data model is a declarative representation of your database schema and serves as the foundation for the generated Prisma Client library. Your Prisma Client instance will expose queries that are _tailored_ to these models. Right now, there's a few minor "issues" with the data model: - The `User` relation field is uppercased and therefore doesn't adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) . To express more "semantics", it would also be nice if this field was called `author` to _describe_ the relationship between `User` and `Post` better. - The `Post` and `Profile` relation fields on `User` as well as the `User` relation field on `Profile` are all uppercased. To adhere to Prisma's [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions-1) , both fields should be lowercased to `post`, `profile` and `user`. - Even after lowercasing, the `post` field on `User` is still slightly misnamed. That's because it actually refers to a [list](/orm/prisma-schema/data-model/models#type-modifiers) of posts – a better name therefore would be the plural form: `posts`. These changes are relevant for the generated Prisma Client API where using lowercased relation fields `author`, `posts`, `profile` and `user` will feel more natural and idiomatic to JavaScript/TypeScript developers. You can therefore [configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). Because [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are _virtual_ (i.e. they _do not directly manifest in the database_), you can manually rename them in your Prisma schema without touching the database: ```prisma file=prisma/schema.prisma highlight=7,14,22,23;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) //edit-next-line author User @relation(fields: [authorId], references: [id]) authorId Int } model Profile { id Int @id @default(autoincrement()) bio String? //edit-next-line user User @relation(fields: [userId], references: [id]) userId Int @unique } model User { id Int @id @default(autoincrement()) email String @unique @db.VarChar(255) name String? @db.VarChar(255) //edit-start posts Post[] profile Profile? //edit-end } ``` In this example, the database schema did follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma ORM models (only the virtual relation fields that were generated from introspection did not adhere to them and needed adjustment). This optimizes the ergonomics of the generated Prisma Client API.
Using custom model and field names Sometimes though, you may want to make additional changes to the names of the columns and tables that are exposed in the Prisma Client API. A common example is to translate _snake_case_ notation which is often used in database schemas into _PascalCase_ and _camelCase_ notations which feel more natural for JavaScript/TypeScript developers. Assume you obtained the following model from introspection that's based on _snake_case_ notation: ```prisma no-lines model my_user { user_id Int @id @default(autoincrement()) first_name String? last_name String @unique } ``` If you generated a Prisma Client API for this model, it would pick up the _snake_case_ notation in its API: ```ts no-lines const user = await prisma.my_user.create({ data: { first_name: 'Alice', last_name: 'Smith', }, }) ``` If you don't want to use the table and column names from your database in your Prisma Client API, you can configure them with [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections): ```prisma no-lines model MyUser { userId Int @id @default(autoincrement()) @map("user_id") firstName String? @map("first_name") lastName String @unique @map("last_name") @@map("my_user") } ``` With this approach, you can name your model and its fields whatever you like and use the `@map` (for field names) and `@@map` (for models names) to point to the underlying tables and columns. Your Prisma Client API now looks as follows: ```ts no-lines const user = await prisma.myUser.create({ data: { firstName: 'Alice', lastName: 'Smith', }, }) ``` Learn more about this on the [Configuring your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) page.
--- # Baseline your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-cockroachdb ## Create an initial migration To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: ```terminal mkdir -p prisma/migrations/0_init ``` `-p` will recursively create any missing folders in the path you provide. Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - `--from-empty`: assumes the data model you're migrating from is empty - `--to-schema-datamodel`: the current database state using the URL in the `datasource` block - `--script`: output a SQL script ```terminal wrap npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql ``` ## Review the migration The command will generate a migration that should resemble the following script: ```sql file=prisma/migrations/0_init/migration.sql CREATE TABLE "User" ( id INT8 PRIMARY KEY DEFAULT unique_rowid(), name STRING(255), email STRING(255) UNIQUE NOT NULL ); CREATE TABLE "Post" ( id INT8 PRIMARY KEY DEFAULT unique_rowid(), title STRING(255) UNIQUE NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), content STRING, published BOOLEAN NOT NULL DEFAULT false, "authorId" INT8 NOT NULL, FOREIGN KEY ("authorId") REFERENCES "User"(id) ); CREATE TABLE "Profile" ( id INT8 PRIMARY KEY DEFAULT unique_rowid(), bio STRING, "userId" INT8 UNIQUE NOT NULL, FOREIGN KEY ("userId") REFERENCES "User"(id) ); ``` Review the SQL migration file to ensure everything is correct. Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. ```terminal npx prisma migrate resolve --applied 0_init ``` The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. --- # Baseline your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-mysql ## Create an initial migration To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: ```terminal mkdir -p prisma/migrations/0_init ``` `-p` will recursively create any missing folders in the path you provide. Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - `--from-empty`: assumes the data model you're migrating from is empty - `--to-schema-datamodel`: the current database state using the URL in the `datasource` block - `--script`: output a SQL script ```terminal wrap npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql ``` ## Review the migration The command will generate a migration that should resemble the following script: ```sql file=prisma/migrations/0_init/migration.sql -- CreateTable CREATE TABLE `Post` ( `id` INTEGER NOT NULL AUTO_INCREMENT, `title` VARCHAR(255) NOT NULL, `createdAt` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0), `content` TEXT NULL, `published` BOOLEAN NOT NULL DEFAULT false, `authorId` INTEGER NOT NULL, INDEX `authorId`(`authorId`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- CreateTable CREATE TABLE `Profile` ( `id` INTEGER NOT NULL AUTO_INCREMENT, `bio` TEXT NULL, `userId` INTEGER NOT NULL, UNIQUE INDEX `userId`(`userId`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- CreateTable CREATE TABLE `User` ( `id` INTEGER NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NULL, `email` VARCHAR(255) NOT NULL, UNIQUE INDEX `email`(`email`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- AddForeignKey ALTER TABLE `Post` ADD CONSTRAINT `Post_ibfk_1` FOREIGN KEY (`authorId`) REFERENCES `User`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT; -- AddForeignKey ALTER TABLE `Profile` ADD CONSTRAINT `Profile_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `User`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT; ``` Review the SQL migration file to ensure everything is correct. Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. ```terminal npx prisma migrate resolve --applied 0_init ``` The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. --- # Baseline your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-postgresql ## Create an initial migration To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: ```terminal mkdir -p prisma/migrations/0_init ``` `-p` will recursively create any missing folders in the path you provide. Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - `--from-empty`: assumes the data model you're migrating from is empty - `--to-schema-datamodel`: the current database state using the URL in the `datasource` block - `--script`: output a SQL script ```terminal wrap npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql ``` ## Review the migration The command will generate a migration that should resemble the following script: ```sql file=prisma/migrations/0_init/migration.sql -- CreateTable CREATE TABLE "Post" ( "id" SERIAL NOT NULL, "title" VARCHAR(255) NOT NULL, "createdAt" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, "content" TEXT, "published" BOOLEAN NOT NULL DEFAULT false, "authorId" INTEGER NOT NULL, CONSTRAINT "Post_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "Profile" ( "id" SERIAL NOT NULL, "bio" TEXT, "userId" INTEGER NOT NULL, CONSTRAINT "Profile_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "User" ( "id" SERIAL NOT NULL, "name" VARCHAR(255), "email" VARCHAR(255) NOT NULL, CONSTRAINT "User_pkey" PRIMARY KEY ("id") ); -- CreateIndex CREATE UNIQUE INDEX "Profile_userId_key" ON "Profile"("userId"); -- CreateIndex CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); -- AddForeignKey ALTER TABLE "Post" ADD CONSTRAINT "Post_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION; -- AddForeignKey ALTER TABLE "Profile" ADD CONSTRAINT "Profile_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION; ``` Review the SQL migration file to ensure everything is correct. Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. ```terminal npx prisma migrate resolve --applied 0_init ``` The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. --- # Baseline your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-node-sqlserver ## Create an initial migration To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: ```terminal mkdir -p prisma/migrations/0_init ``` `-p` will recursively create any missing folders in the path you provide. Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - `--from-empty`: assumes the data model you're migrating from is empty - `--to-schema-datamodel`: the current database state using the URL in the `datasource` block - `--script`: output a SQL script ```terminal wrap npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql ``` ## Review the migration The command will generate a migration that should resemble the following script: ```sql file=prisma/migrations/0_init/migration.sql CREATE TABLE [dbo].[Post] ( [id] INT NOT NULL IDENTITY(1,1), [createdAt] DATETIME2 NOT NULL CONSTRAINT [Post_createdAt_df] DEFAULT CURRENT_TIMESTAMP, [updatedAt] DATETIME2 NOT NULL, [title] VARCHAR(255) NOT NULL, [content] NVARCHAR(1000), [published] BIT NOT NULL CONSTRAINT [Post_published_df] DEFAULT 0, [authorId] INT NOT NULL, CONSTRAINT [Post_pkey] PRIMARY KEY ([id]) ); CREATE TABLE [dbo].[Profile] ( [id] INT NOT NULL IDENTITY(1,1), [bio] NVARCHAR(1000), [userId] INT NOT NULL, CONSTRAINT [Profile_pkey] PRIMARY KEY ([id]), CONSTRAINT [Profile_userId_key] UNIQUE ([userId]) ); CREATE TABLE [dbo].[User] ( [id] INT NOT NULL IDENTITY(1,1), [email] NVARCHAR(1000) NOT NULL, [name] NVARCHAR(1000), CONSTRAINT [User_pkey] PRIMARY KEY ([id]), CONSTRAINT [User_email_key] UNIQUE ([email]) ); ALTER TABLE [dbo].[Post] ADD CONSTRAINT [Post_authorId_fkey] FOREIGN KEY ([authorId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; ALTER TABLE [dbo].[Profile] ADD CONSTRAINT [Profile_userId_fkey] FOREIGN KEY ([userId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; ``` Review the SQL migration file to ensure everything is correct. Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. ```terminal npx prisma migrate resolve --applied 0_init ``` The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. --- # Baseline your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-cockroachdb ## Create an initial migration To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: ```terminal mkdir -p prisma/migrations/0_init ``` `-p` will recursively create any missing folders in the path you provide. Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - `--from-empty`: assumes the data model you're migrating from is empty - `--to-schema-datamodel`: the current database state using the URL in the `datasource` block - `--script`: output a SQL script ```terminal wrap npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql ``` ## Review the migration The command will generate a migration that should resemble the following script: ```sql file=prisma/migrations/0_init/migration.sql CREATE TABLE "User" ( id INT8 PRIMARY KEY DEFAULT unique_rowid(), name STRING(255), email STRING(255) UNIQUE NOT NULL ); CREATE TABLE "Post" ( id INT8 PRIMARY KEY DEFAULT unique_rowid(), title STRING(255) UNIQUE NOT NULL, "createdAt" TIMESTAMP NOT NULL DEFAULT now(), content STRING, published BOOLEAN NOT NULL DEFAULT false, "authorId" INT8 NOT NULL, FOREIGN KEY ("authorId") REFERENCES "User"(id) ); CREATE TABLE "Profile" ( id INT8 PRIMARY KEY DEFAULT unique_rowid(), bio STRING, "userId" INT8 UNIQUE NOT NULL, FOREIGN KEY ("userId") REFERENCES "User"(id) ); ``` --- # Baseline your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-mysql ## Create an initial migration To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: ```terminal mkdir -p prisma/migrations/0_init ``` `-p` will recursively create any missing folders in the path you provide. Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - `--from-empty`: assumes the data model you're migrating from is empty - `--to-schema-datamodel`: the current database state using the URL in the `datasource` block - `--script`: output a SQL script ```terminal wrap npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql ``` ## Review the migration The command will generate a migration that should resemble the following script: ```sql file=prisma/migrations/0_init/migration.sql -- CreateTable CREATE TABLE `Post` ( `id` INTEGER NOT NULL AUTO_INCREMENT, `title` VARCHAR(255) NOT NULL, `createdAt` TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0), `content` TEXT NULL, `published` BOOLEAN NOT NULL DEFAULT false, `authorId` INTEGER NOT NULL, INDEX `authorId`(`authorId`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- CreateTable CREATE TABLE `Profile` ( `id` INTEGER NOT NULL AUTO_INCREMENT, `bio` TEXT NULL, `userId` INTEGER NOT NULL, UNIQUE INDEX `userId`(`userId`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- CreateTable CREATE TABLE `User` ( `id` INTEGER NOT NULL AUTO_INCREMENT, `name` VARCHAR(255) NULL, `email` VARCHAR(255) NOT NULL, UNIQUE INDEX `email`(`email`), PRIMARY KEY (`id`) ) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- AddForeignKey ALTER TABLE `Post` ADD CONSTRAINT `Post_ibfk_1` FOREIGN KEY (`authorId`) REFERENCES `User`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT; -- AddForeignKey ALTER TABLE `Profile` ADD CONSTRAINT `Profile_ibfk_1` FOREIGN KEY (`userId`) REFERENCES `User`(`id`) ON DELETE RESTRICT ON UPDATE RESTRICT; ``` Review the SQL migration file to ensure everything is correct. Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. ```terminal npx prisma migrate resolve --applied 0_init ``` The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. --- # Baseline your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-postgresql ## Create an initial migration To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: ```terminal mkdir -p prisma/migrations/0_init ``` `-p` will recursively create any missing folders in the path you provide. Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - `--from-empty`: assumes the data model you're migrating from is empty - `--to-schema-datamodel`: the current database state using the URL in the `datasource` block - `--script`: output a SQL script ```terminal wrap npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql ``` ## Review the migration The command will generate a migration that should resemble the following script: ```sql file=prisma/migrations/0_init/migration.sql -- CreateTable CREATE TABLE "Post" ( "id" SERIAL NOT NULL, "title" VARCHAR(255) NOT NULL, "createdAt" TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP, "content" TEXT, "published" BOOLEAN NOT NULL DEFAULT false, "authorId" INTEGER NOT NULL, CONSTRAINT "Post_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "Profile" ( "id" SERIAL NOT NULL, "bio" TEXT, "userId" INTEGER NOT NULL, CONSTRAINT "Profile_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "User" ( "id" SERIAL NOT NULL, "name" VARCHAR(255), "email" VARCHAR(255) NOT NULL, CONSTRAINT "User_pkey" PRIMARY KEY ("id") ); -- CreateIndex CREATE UNIQUE INDEX "Profile_userId_key" ON "Profile"("userId"); -- CreateIndex CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); -- AddForeignKey ALTER TABLE "Post" ADD CONSTRAINT "Post_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION; -- AddForeignKey ALTER TABLE "Profile" ADD CONSTRAINT "Profile_userId_fkey" FOREIGN KEY ("userId") REFERENCES "User"("id") ON DELETE NO ACTION ON UPDATE NO ACTION; ``` Review the SQL migration file to ensure everything is correct. Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. ```terminal npx prisma migrate resolve --applied 0_init ``` The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. --- # Baseline your database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-sqlserver ## Create an initial migration To use Prisma Migrate with the database you introspected in the last section, you will need to [baseline your database](/orm/prisma-migrate/getting-started). Baselining refers to initializing your migration history for a database that might already contain data and **cannot be reset**, such as your production database. Baselining tells Prisma Migrate to assume that one or more migrations have already been applied to your database. To baseline your database, use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to compare your schema and database, and save the output into a SQL file. First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: ```terminal mkdir -p prisma/migrations/0_init ``` `-p` will recursively create any missing folders in the path you provide. Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - `--from-empty`: assumes the data model you're migrating from is empty - `--to-schema-datamodel`: the current database state using the URL in the `datasource` block - `--script`: output a SQL script ```terminal wrap npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql ``` ## Review the migration The command will generate a migration that should resemble the following script: ```sql file=prisma/migrations/0_init/migration.sql CREATE TABLE [dbo].[Post] ( [id] INT NOT NULL IDENTITY(1,1), [createdAt] DATETIME2 NOT NULL CONSTRAINT [Post_createdAt_df] DEFAULT CURRENT_TIMESTAMP, [updatedAt] DATETIME2 NOT NULL, [title] VARCHAR(255) NOT NULL, [content] NVARCHAR(1000), [published] BIT NOT NULL CONSTRAINT [Post_published_df] DEFAULT 0, [authorId] INT NOT NULL, CONSTRAINT [Post_pkey] PRIMARY KEY ([id]) ); CREATE TABLE [dbo].[Profile] ( [id] INT NOT NULL IDENTITY(1,1), [bio] NVARCHAR(1000), [userId] INT NOT NULL, CONSTRAINT [Profile_pkey] PRIMARY KEY ([id]), CONSTRAINT [Profile_userId_key] UNIQUE ([userId]) ); CREATE TABLE [dbo].[User] ( [id] INT NOT NULL IDENTITY(1,1), [email] NVARCHAR(1000) NOT NULL, [name] NVARCHAR(1000), CONSTRAINT [User_pkey] PRIMARY KEY ([id]), CONSTRAINT [User_email_key] UNIQUE ([email]) ); ALTER TABLE [dbo].[Post] ADD CONSTRAINT [Post_authorId_fkey] FOREIGN KEY ([authorId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; ALTER TABLE [dbo].[Profile] ADD CONSTRAINT [Profile_userId_fkey] FOREIGN KEY ([userId]) REFERENCES [dbo].[User]([id]) ON DELETE NO ACTION ON UPDATE CASCADE; ``` Review the SQL migration file to ensure everything is correct. Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. ```terminal npx prisma migrate resolve --applied 0_init ``` The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-cockroachdb import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-mysql import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-planetscale import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-postgresql import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-sqlserver import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-cockroachdb import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-mysql import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-planetscale import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-postgresql import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-typescript-sqlserver import InstallPrismaClient from './_install-prisma-client-partial.mdx' --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-cockroachdb ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). Create a new file named `index.js` and add the following code to it: ```js file=index.js showLineNumbers const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` ```js file=index.js async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` Now run the code with this command: ```terminal copy node index.js ``` If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. ```no-copy [] ``` If you introspected an existing database with records, the query should return an array of JavaScript objects. ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```js file=index.js showLineNumbers async function main() { await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy node index.js ``` Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```js file=index.js showLineNumbers async function main() { const post = await prisma.post.update({ where: { title: 'Hello World' }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy node index.js ``` --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-mysql ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). Create a new file named `index.js` and add the following code to it: ```js file=index.js showLineNumbers const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` ```js file=index.js async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` Now run the code with this command: ```terminal copy node index.js ``` If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. ```no-copy [] ``` If you introspected an existing database with records, the query should return an array of JavaScript objects. ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```js file=index.js showLineNumbers async function main() { await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy node index.js ``` Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```js file=index.js showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy node index.js ``` --- --- title: 'Querying the database' metaTitle: 'Query your existing PlanetScale database with JavaScript and Prisma ORM' metaDescription: 'Write data to and query the PlanetScale database with your JavaScript and Prisma ORM project' langSwitcher: ['typescript', 'node'] dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] hide_table_of_contents: true sidebar_class_name: hidden-sidebar pagination_prev: getting-started/setup-prisma/add-to-existing-project/relational-databases/install-prisma-client-node-postgresql pagination_next: getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-postgresql slugSwitch: /getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database- --- ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). Create a new file named `index.js` and add the following code to it: ```js file=index.js showLineNumbers const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). The following examples are all based on the models in the Prisma schema. Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```js file=index.js showLineNumbers async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` Now run the code with this command: ```terminal copy node index.js ``` If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. ```no-copy [] ``` If you introspected an existing database with records, the query should return an array of JavaScript objects. ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```js file=index.js showLineNumbers async function main() { await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy node index.js ``` Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```js file=index.js async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy node index.js ``` --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-postgresql ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). Create a new file named `index.js` and add the following code to it: ```js file=index.js showLineNumbers const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` ```js file=index.js showLineNumbers async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` Now run the code with this command: ```terminal copy node index.js ``` If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. ```no-copy [] ``` If you introspected an existing database with records, the query should return an array of JavaScript objects. ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```js file=index.js showLineNumbers async function main() { await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy node index.js ``` Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```js file=index.js async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Now run the code using the same command as before: ```terminal copy node index.js ``` --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-node-sqlserver ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). Create a new file named `index.js` and add the following code to it: ```js file=index.js showLineNumbers const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). The following examples are all based on the models in the Prisma schema. Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```js file=index.js showLineNumbers async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` Now run the code with this command: ```terminal copy node index.js ``` If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. ```no-copy [] ``` If you introspected an existing database with records, the query should return an array of JavaScript objects. ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```js file=index.js showLineNumbers async function main() { await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with this command: ```terminal copy node index.js ``` Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```js file=index.js async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-cockroachdb ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). Create a new file named `index.ts` and add the following code to it: ```ts file=index.ts showLineNumbers import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). The following examples are all based on the models in the Prisma schema. Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```ts file=index.ts showLineNumbers async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` Now run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. ```no-copy [] ``` If you introspected an existing database with records, the query should return an array of JavaScript objects. ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```ts file=index.ts showLineNumbers async function main() { await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```ts file=index.ts showLineNumbers async function main() { const post = await prisma.post.update({ where: { title: 'Hello World' }, data: { published: true }, }) console.log(post) } ``` Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-mysql ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). Create a new file named `index.ts` and add the following code to it: ```ts file=index.ts showLineNumbers import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). The following examples are all based on the models in the Prisma schema. Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```ts file=index.ts showLineNumbers async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` Now run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. ```no-copy [] ``` If you introspected an existing database with records, the query should return an array of JavaScript objects. ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```ts file=index.ts showLineNumbers async function main() { await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```ts file=index.ts showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-planetscale ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). Create a new file named `index.ts` and add the following code to it: ```ts file=index.ts showLineNumbers import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). The following examples are all based on the models in the Prisma schema. Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```ts file=index.ts showLineNumbers async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` Now run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. ```no-copy [] ``` If you introspected an existing database with records, the query should return an array of JavaScript objects. ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```ts file=index.ts showLineNumbers async function main() { await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```ts file=index.ts showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-postgresql ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). Create a new file named `index.ts` and add the following code to it: ```ts file=index.ts showLineNumbers import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). The following examples are all based on the models in the Prisma schema. Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```ts file=index.ts showLineNumbers async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` Now run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. ```no-copy [] ``` If you introspected an existing database with records, the query should return an array of JavaScript objects. ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```ts file=index.ts showLineNumbers async function main() { await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```ts file=index.ts showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/querying-the-database-typescript-sqlserver ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). Create a new file named `index.ts` and add the following code to it: ```ts file=index.ts showLineNumbers import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Call the `main` function 1. Close the database connections when the script terminates Depending on what your models look like, the Prisma Client API will look different as well. For example, if you have a `User` model, your `PrismaClient` instance exposes a property called `user` on which you can call [CRUD](/orm/prisma-client/queries/crud) methods like `findMany`, `create` or `update`. The property is named after the model, but the first letter is lowercased (so for the `Post` model it's called `post`, for `Profile` it's called `profile`). The following examples are all based on the models in the Prisma schema. Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```ts file=index.ts showLineNumbers async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` Now run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` If you created a database using the schema from the database introspection step, the query should print an empty array because there are no `User` records in the database yet. ```no-copy [] ``` If you introspected an existing database with records, the query should return an array of JavaScript objects. ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database. In this section, you'll learn how to write a query to _write_ new records into the `Post` and `User` tables. Adjust the `main` function to send a `create` query to the database: ```ts file=index.ts showLineNumbers async function main() { await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, profile: { create: { bio: 'I like turtles' }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, profile: true, }, }) console.dir(allUsers, { depth: null }) } ``` This code creates a new `User` record together with new `Post` and `Profile` records using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the two other ones via the `Post.author` ↔ `User.posts` and `Profile.user` ↔ `User.profile` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` and `profile` relations on the returned `User` objects. Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` Before moving on to the next section, you'll "publish" the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```ts file=index.ts showLineNumbers async function main() { const post = await prisma.post.update({ where: { id: 1 }, data: { published: true }, }) console.log(post) } ``` Run the code with your current TypeScript setup. If you're using `tsx`, you can run it like this: ```terminal copy npx tsx index.ts ``` --- # Evolve your schema URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-cockroachdb ## Add a `Tag` model to your schema In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). For the purpose of this guide, we'll make the following changes to the Prisma schema: 1. Create a new model called `Tag` with the following fields: - `id`: an auto-incrementing integer that will be the primary key for the model - `name`: a non-null `String` - `posts`: an implicit many-to-many relation field that links to the `Post` model 2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model Once you've made the changes to your schema, your schema should resemble the one below: ```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int user User @relation(fields: [authorId], references: [id]) //edit-next-line tags Tag[] } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique user User @relation(fields: [userId], references: [id]) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) post Post[] profile Profile? } //edit-start model Tag { id Int @id @default(autoincrement()) name String posts Post[] } //edit-end ``` To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: ```terminal copy npx prisma migrate dev --name tags-model ``` This command will: 1. Create a new SQL migration file for the migration 1. Apply the generated SQL migration to the database 1. Regenerate Prisma Client The following migration will be generated and saved in your `prisma/migrations` folder: ```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers -- CreateTable CREATE TABLE "Tag" ( "id" SERIAL NOT NULL, "name" VARCHAR(255) NOT NULL, CONSTRAINT "Tag_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "_PostToTag" ( "A" INTEGER NOT NULL, "B" INTEGER NOT NULL ); -- CreateIndex CREATE UNIQUE INDEX "_PostToTag_AB_unique" ON "_PostToTag"("A", "B"); -- CreateIndex CREATE INDEX "_PostToTag_B_index" ON "_PostToTag"("B"); -- AddForeignKey ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Post"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; ``` --- # Evolve your schema URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-mysql ## Add a `Tag` model to your schema In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). For the purpose of this guide, we'll make the following changes to the Prisma schema: 1. Create a new model called `Tag` with the following fields: - `id`: an auto-incrementing integer that will be the primary key for the model - `name`: a non-null `String` - `posts`: an implicit many-to-many relation field that links to the `Post` model 2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model Once you've made the changes to your schema, your schema should resemble the one below: ```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int user User @relation(fields: [authorId], references: [id]) //edit-next-line tags Tag[] } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique user User @relation(fields: [userId], references: [id]) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) post Post[] profile Profile? } //edit-start model Tag { id Int @id @default(autoincrement()) name String posts Post[] } //edit-end ``` To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: ```terminal copy npx prisma migrate dev --name tags-model ``` This command will: 1. Create a new SQL migration file for the migration 1. Apply the generated SQL migration to the database 1. Regenerate Prisma Client The following migration will be generated and saved in your `prisma/migrations` folder: ```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers -- CreateTable CREATE TABLE Tag ( id SERIAL NOT NULL, name VARCHAR(255) NOT NULL, CONSTRAINT Tag_pkey PRIMARY KEY (id) ); -- CreateTable CREATE TABLE _PostToTag ( A INTEGER NOT NULL, B INTEGER NOT NULL ); -- CreateIndex CREATE UNIQUE INDEX _PostToTag_AB_unique ON _PostToTag(A, B); -- CreateIndex CREATE INDEX _PostToTag_B_index ON _PostToTag(B); -- AddForeignKey ALTER TABLE _PostToTag ADD CONSTRAINT _PostToTag_A_fkey FOREIGN KEY (A) REFERENCES Post(id) ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE _PostToTag ADD CONSTRAINT _PostToTag_B_fkey FOREIGN KEY (B) REFERENCES Tag(id) ON DELETE CASCADE ON UPDATE CASCADE; ``` Congratulations, you just evolved your database with Prisma Migrate 🚀 --- # Evolve your schema URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-postgresql ## Add a `Tag` model to your schema In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). For the purpose of this guide, we'll make the following changes to the Prisma schema: 1. Create a new model called `Tag` with the following fields: - `id`: an auto-incrementing integer that will be the primary key for the model - `name`: a non-null `String` - `posts`: an implicit many-to-many relation field that links to the `Post` model 2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model Once you've made the changes to your schema, your schema should resemble the one below: ```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int user User @relation(fields: [authorId], references: [id]) //edit-next-line tags Tag[] } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique user User @relation(fields: [userId], references: [id]) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) post Post[] profile Profile? } //edit-start model Tag { id Int @id @default(autoincrement()) name String posts Post[] } //edit-end ``` To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: ```terminal copy npx prisma migrate dev --name tags-model ``` This command will: 1. Create a new SQL migration file for the migration 1. Apply the generated SQL migration to the database 1. Regenerate Prisma Client The following migration will be generated and saved in your `prisma/migrations` folder: ```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers -- CreateTable CREATE TABLE "Tag" ( "id" SERIAL NOT NULL, "name" VARCHAR(255) NOT NULL, CONSTRAINT "Tag_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "_PostToTag" ( "A" INTEGER NOT NULL, "B" INTEGER NOT NULL ); -- CreateIndex CREATE UNIQUE INDEX "_PostToTag_AB_unique" ON "_PostToTag"("A", "B"); -- CreateIndex CREATE INDEX "_PostToTag_B_index" ON "_PostToTag"("B"); -- AddForeignKey ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Post"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; ``` Congratulations, you just evolved your database with Prisma Migrate 🚀 --- # Evolve your schema URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-node-sqlserver ## Add a `Tag` model to your schema In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). For the purpose of this guide, we'll make the following changes to the Prisma schema: 1. Create a new model called `Tag` with the following fields: - `id`: an auto-incrementing integer that will be the primary key for the model - `name`: a non-null `String` - `posts`: an implicit many-to-many relation field that links to the `Post` model 2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model Once you've made the changes to your schema, your schema should resemble the one below: ```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int user User @relation(fields: [authorId], references: [id]) //edit-next-line tags Tag[] } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique user User @relation(fields: [userId], references: [id]) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) post Post[] profile Profile? } //edit-start model Tag { id Int @id @default(autoincrement()) name String posts Post[] } //edit-end ``` To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: ```terminal copy npx prisma migrate dev --name tags-model ``` This command will: 1. Create a new SQL migration file for the migration 1. Apply the generated SQL migration to the database 1. Regenerate Prisma Client The following migration will be generated and saved in your `prisma/migrations` folder: ```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers -- CreateTable CREATE TABLE [dbo].[Tag] ( [id] SERIAL NOT NULL, [name] VARCHAR(255) NOT NULL, CONSTRAINT [Tag_pkey] PRIMARY KEY ([id]) ); -- CreateTable CREATE TABLE [dbo].[_PostToTag] ( [A] INTEGER NOT NULL, [B] INTEGER NOT NULL ); -- CreateIndex CREATE UNIQUE INDEX [_PostToTag_AB_unique] ON _PostToTag([A], [B]); -- CreateIndex CREATE INDEX [_PostToTag_B_index] ON [_PostToTag]([B]); -- AddForeignKey ALTER TABLE [dbo].[_PostToTag] ADD CONSTRAINT [_PostToTag_A_fkey] FOREIGN KEY ([A]) REFERENCES [dbo].[Post]([id]) ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE [dbo].[_PostToTag] ADD CONSTRAINT [_PostToTag_B_fkey] FOREIGN KEY ([B]) REFERENCES [dbo].[Tag]([id]) ON DELETE CASCADE ON UPDATE CASCADE; ``` Congratulations --- # Evolve your schema URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-cockroachdb ## Add a `Tag` model to your schema In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). For the purpose of this guide, we'll make the following changes to the Prisma schema: 1. Create a new model called `Tag` with the following fields: - `id`: an auto-incrementing integer that will be the primary key for the model - `name`: a non-null `String` - `posts`: an implicit many-to-many relation field that links to the `Post` model 2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model Once you've made the changes to your schema, your schema should resemble the one below: ```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int user User @relation(fields: [authorId], references: [id]) //edit-next-line tags Tag[] } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique user User @relation(fields: [userId], references: [id]) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) post Post[] profile Profile? } //edit-start model Tag { id Int @id @default(autoincrement()) name String posts Post[] } //edit-end ``` To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: ```terminal copy npx prisma migrate dev --name tags-model ``` This command will: 1. Create a new SQL migration file for the migration 1. Apply the generated SQL migration to the database 1. Regenerate Prisma Client The following migration will be generated and saved in your `prisma/migrations` folder: ```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers -- CreateTable CREATE TABLE "Tag" ( "id" SERIAL NOT NULL, "name" VARCHAR(255) NOT NULL, CONSTRAINT "Tag_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "_PostToTag" ( "A" INTEGER NOT NULL, "B" INTEGER NOT NULL ); -- CreateIndex CREATE UNIQUE INDEX "_PostToTag_AB_unique" ON "_PostToTag"("A", "B"); -- CreateIndex CREATE INDEX "_PostToTag_B_index" ON "_PostToTag"("B"); -- AddForeignKey ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Post"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; ``` Congratulations, you just evolved your database with Prisma Migrate 🚀 --- # Evolve your schema URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-mysql ## Add a `Tag` model to your schema In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). For the purpose of this guide, we'll make the following changes to the Prisma schema: 1. Create a new model called `Tag` with the following fields: - `id`: an auto-incrementing integer that will be the primary key for the model - `name`: a non-null `String` - `posts`: an implicit many-to-many relation field that links to the `Post` model 2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model Once you've made the changes to your schema, your schema should resemble the one below: ```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int user User @relation(fields: [authorId], references: [id]) //edit-next-line tags Tag[] } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique user User @relation(fields: [userId], references: [id]) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) post Post[] profile Profile? } //edit-start model Tag { id Int @id @default(autoincrement()) name String posts Post[] } //edit-end ``` To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: ```terminal copy npx prisma migrate dev --name tags-model ``` This command will: 1. Create a new SQL migration file for the migration 1. Apply the generated SQL migration to the database 1. Regenerate Prisma Client The following migration will be generated and saved in your `prisma/migrations` folder: ```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers -- CreateTable CREATE TABLE Tag ( id SERIAL NOT NULL, name VARCHAR(255) NOT NULL, CONSTRAINT Tag_pkey PRIMARY KEY (id) ); -- CreateTable CREATE TABLE _PostToTag ( A INTEGER NOT NULL, B INTEGER NOT NULL ); -- CreateIndex CREATE UNIQUE INDEX _PostToTag_AB_unique ON _PostToTag(A, B); -- CreateIndex CREATE INDEX _PostToTag_B_index ON _PostToTag(B); -- AddForeignKey ALTER TABLE _PostToTag ADD CONSTRAINT _PostToTag_A_fkey FOREIGN KEY (A) REFERENCES Post(id) ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE _PostToTag ADD CONSTRAINT _PostToTag_B_fkey FOREIGN KEY (B) REFERENCES Tag(id) ON DELETE CASCADE ON UPDATE CASCADE; ``` Congratulations, you just evolved your database with Prisma Migrate 🚀 --- # Evolve your schema URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-postgresql ## Add a `Tag` model to your schema In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). For the purpose of this guide, we'll make the following changes to the Prisma schema: 1. Create a new model called `Tag` with the following fields: - `id`: an auto-incrementing integer that will be the primary key for the model - `name`: a non-null `String` - `posts`: an implicit many-to-many relation field that links to the `Post` model 2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model Once you've made the changes to your schema, your schema should resemble the one below: ```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int user User @relation(fields: [authorId], references: [id]) //edit-next-line tags Tag[] } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique user User @relation(fields: [userId], references: [id]) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) post Post[] profile Profile? } //edit-start model Tag { id Int @id @default(autoincrement()) name String posts Post[] } //edit-end ``` To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: ```terminal copy npx prisma migrate dev --name tags-model ``` This command will: 1. Create a new SQL migration file for the migration 1. Apply the generated SQL migration to the database 1. Regenerate Prisma Client The following migration will be generated and saved in your `prisma/migrations` folder: ```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers -- CreateTable CREATE TABLE "Tag" ( "id" SERIAL NOT NULL, "name" VARCHAR(255) NOT NULL, CONSTRAINT "Tag_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "_PostToTag" ( "A" INTEGER NOT NULL, "B" INTEGER NOT NULL ); -- CreateIndex CREATE UNIQUE INDEX "_PostToTag_AB_unique" ON "_PostToTag"("A", "B"); -- CreateIndex CREATE INDEX "_PostToTag_B_index" ON "_PostToTag"("B"); -- AddForeignKey ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Post"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; ``` Congratulations, you just evolved your database with Prisma Migrate 🚀 --- # Evolve your schema URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/evolve-your-schema-typescript-sqlserver ## Add a `Tag` model to your schema In this section, you will evolve your Prisma schema and then generate and apply the migration to your database with [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev). For the purpose of this guide, we'll make the following changes to the Prisma schema: 1. Create a new model called `Tag` with the following fields: - `id`: an auto-incrementing integer that will be the primary key for the model - `name`: a non-null `String` - `posts`: an implicit many-to-many relation field that links to the `Post` model 2. Update the `Post` model with a `tags` field with an implicit many-to-many relation field that links to the `Tag` model Once you've made the changes to your schema, your schema should resemble the one below: ```prisma file=prisma/schema.prisma highlight=9,27-31;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) createdAt DateTime @default(now()) @db.Timestamp(6) content String? published Boolean @default(false) authorId Int user User @relation(fields: [authorId], references: [id]) //edit-next-line tags Tag[] } model Profile { id Int @id @default(autoincrement()) bio String? userId Int @unique user User @relation(fields: [userId], references: [id]) } model User { id Int @id @default(autoincrement()) name String? @db.VarChar(255) email String @unique @db.VarChar(255) post Post[] profile Profile? } //edit-start model Tag { id Int @id @default(autoincrement()) name String posts Post[] } //edit-end ``` To apply your Prisma schema changes to your database, use the `prisma migrate dev` CLI command: ```terminal copy npx prisma migrate dev --name tags-model ``` This command will: 1. Create a new SQL migration file for the migration 1. Apply the generated SQL migration to the database 1. Regenerate Prisma Client The following migration will be generated and saved in your `prisma/migrations` folder: ```sql file=prisma/migrations/TIMESTAMP_tags_model.sql showLineNumbers -- CreateTable CREATE TABLE [dbo].[Tag] ( [id] SERIAL NOT NULL, [name] VARCHAR(255) NOT NULL, CONSTRAINT [Tag_pkey] PRIMARY KEY ([id]) ); -- CreateTable CREATE TABLE [dbo].[_PostToTag] ( [A] INTEGER NOT NULL, [B] INTEGER NOT NULL ); -- CreateIndex CREATE UNIQUE INDEX [_PostToTag_AB_unique] ON _PostToTag([A], [B]); -- CreateIndex CREATE INDEX [_PostToTag_B_index] ON [_PostToTag]([B]); -- AddForeignKey ALTER TABLE [dbo].[_PostToTag] ADD CONSTRAINT [_PostToTag_A_fkey] FOREIGN KEY ([A]) REFERENCES [dbo].[Post]([id]) ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE [dbo].[_PostToTag] ADD CONSTRAINT [_PostToTag_B_fkey] FOREIGN KEY ([B]) REFERENCES [dbo].[Tag]([id]) ON DELETE CASCADE ON UPDATE CASCADE; ``` Congratulations, you just evolved your database with Prisma Migrate 🚀 --- # Next steps URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases/next-steps This section lists a number of potential next steps you can now take from here. Feel free to explore these or read the [Introduction](/orm/overview/introduction/what-is-prisma) page to get a high-level overview of Prisma ORM. ### Continue exploring the Prisma Client API You can send a variety of queries with the Prisma Client API. Check out the [API reference](/orm/prisma-client) and use your existing database setup from this guide to try them out. :::tip You can use your editor's auto-completion feature to learn about the different API calls and the arguments it takes. Auto-completion is commonly invoked by hitting CTRL+SPACE on your keyboard. :::
Expand for more Prisma Client API examples Here are a few suggestions for a number of more queries you can send with Prisma Client: **Filter all `Post` records that contain `"hello"`** ```js const filteredPosts = await prisma.post.findMany({ where: { OR: [ { title: { contains: "hello" }, { content: { contains: "hello" }, ], }, }) ``` **Create a new `Post` record and connect it to an existing `User` record** ```js const post = await prisma.post.create({ data: { title: 'Join us for Prisma Day 2020', author: { connect: { email: 'alice@prisma.io' }, }, }, }) ``` **Use the fluent relations API to retrieve the `Post` records of a `User` by traversing the relations** ```js const posts = await prisma.profile .findUnique({ where: { id: 1 }, }) .user() .posts() ``` **Delete a `User` record** ```js const deletedUser = await prisma.user.delete({ where: { email: 'sarah@prisma.io' }, }) ```
### Build an app with Prisma ORM The Prisma blog features comprehensive tutorials about Prisma ORM, check out our latest ones: - [Build a fullstack app with Next.js](https://www.youtube.com/watch?v=QXxy8Uv1LnQ&ab_channel=ByteGrad) - [Build a fullstack app with Remix](https://www.prisma.io/blog/fullstack-remix-prisma-mongodb-1-7D0BfTXBmB6r) (5 parts, including videos) - [Build a REST API with NestJS](https://www.prisma.io/blog/nestjs-prisma-rest-api-7D056s1BmOL0) ### Explore the data in Prisma Studio Prisma Studio is a visual editor for the data in your database. Run `npx prisma studio` in your terminal. ### Get query insights and analytics with Prisma Optimize [Prisma Optimize](/optimize) helps you generate insights and provides recommendations that can help you make your database queries faster. [Try it out now!](/optimize/getting-started) Optimize aims to help developers of all skill levels write efficient database queries, reducing database load and making applications more responsive. ### Change the database schema (e.g. add more tables) To evolve the app, you need to follow the same flow of the tutorial: 1. Manually adjust your database schema using SQL 1. Re-introspect your database 1. Optionally re-configure your Prisma Client API 1. Re-generate Prisma Client ![Introspect workflow](/img/getting-started/prisma-evolve-app-workflow.png) ### Try a Prisma ORM example The [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository contains a number of ready-to-run examples: | Demo | Stack | Description | | :------------------------------------------------------------------------------------------------------------------ | :----------- | --------------------------------------------------------------------------------------------------- | | [`nextjs`](https://pris.ly/e/orm/nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app | | [`nextjs-graphql`](https://pris.ly/e/ts/graphql-nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app (React) with a GraphQL API | | [`graphql-nexus`](https://pris.ly/e/ts/graphql-nexus) | Backend only | GraphQL server based on [`@apollo/server`](https://www.apollographql.com/docs/apollo-server) | | [`express`](https://pris.ly/e/ts/rest-express) | Backend only | Simple REST API with Express.JS | | [`grpc`](https://pris.ly/e/ts/grpc) | Backend only | Simple gRPC API | --- ## Install and generate Prisma Client To get started with Prisma Client, first install the `@prisma/client` package: ```terminal copy npm install @prisma/client ``` Then, run `prisma generate` which reads your Prisma schema and generates the Prisma Client. ```terminal copy npx prisma generate ``` You can now import the `PrismaClient` constructor from the `@prisma/client` package to create an instance of Prisma Client to send queries to your database. You'll learn how to do that in the next section. :::note Good to know When you run `prisma generate`, you are actually creating code (TypeScript types, methods, queries, ...) that is tailored to _your_ Prisma schema file or files in the `prisma` directory. This means, that whenever you make changes to your Prisma schema file, you also need to update the Prisma Client. You can do this by running the `prisma generate` command. ![Install and generate Prisma Client](/img/getting-started/prisma-client-install-and-generate.png) Whenever you update your Prisma schema, you will have to update your database schema using either `prisma migrate dev` or `prisma db push`. This will keep your database schema in sync with your Prisma schema. These commands will also run `prisma generate` under the hood to re-generate your Prisma Client. ::: --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-node-cockroachdb Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). :::tip If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. ::: ## Prerequisites In order to successfully complete this guide, you need: - an existing Node.js project with a `package.json` - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [CockroachDB](https://www.cockroachlabs.com) database server running and a database with at least one table > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Set up Prisma ORM As a first step, navigate into your project directory that contains the `package.json` file. Next, add the Prisma CLI as a development dependency to your project: ```terminal copy npm install prisma --save-dev ``` :::note If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-node-mysql Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). :::tip If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. ::: ## Prerequisites In order to successfully complete this guide, you need: - an existing Node.js project with a `package.json` - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [MySQL](https://www.mysql.com/) database server running and a database with at least one table > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Set up Prisma ORM As a first step, navigate into your project directory that contains the `package.json` file. Next, add the Prisma CLI as a development dependency to your project: ```terminal copy npm install prisma --save-dev ``` :::note If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-node-planetscale Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). :::tip If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. ::: ## Prerequisites In order to successfully complete this guide, you need: - an existing Node.js project with a `package.json` - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [PlanetScale](https://planetscale.com/) database server running and a database with at least one table > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Set up Prisma ORM As a first step, navigate into your project directory that contains the `package.json` file. Next, add the Prisma CLI as a development dependency to your project: ```terminal copy npm install prisma --save-dev ``` :::note If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-node-postgresql Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). :::tip If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. ::: ## Prerequisites In order to successfully complete this guide, you need: - an existing Node.js project with a `package.json` - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [PostgreSQL](https://www.postgresql.org/) database server running and a database with at least one table > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Set up Prisma ORM As a first step, navigate into your project directory that contains the `package.json` file. Next, add the Prisma CLI as a development dependency to your project: ```terminal copy npm install prisma --save-dev ``` :::note If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-node-sqlserver Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). :::tip If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. ::: ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - A [Microsoft SQL Server](https://learn.microsoft.com/en-us/sql/?view=sql-server-ver16) database - [Microsoft SQL Server on Linux for Docker](/orm/overview/databases/sql-server/sql-server-docker) - [Microsoft SQL Server on Windows (local)](/orm/overview/databases/sql-server/sql-server-local) > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Set up Prisma ORM As a first step, navigate into your project directory that contains the `package.json` file. Next, add the Prisma CLI as a development dependency to your project: ```terminal copy npm install prisma --save-dev ``` :::note If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-cockroachdb Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). :::tip If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. ::: ## Prerequisites In order to successfully complete this guide, you need: - an existing Node.js project with a `package.json` - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [CockroachDB](https://www.cockroachlabs.com) database server running and a database with at least one table > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Set up Prisma ORM As a first step, navigate into your project directory that contains the `package.json` file. Next, add the Prisma CLI as a development dependency to your project: ```terminal copy npm install prisma --save-dev ``` :::note If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-mysql Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). :::tip If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. ::: ## Prerequisites In order to successfully complete this guide, you need: - an existing Node.js project with a `package.json` - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [MySQL](https://www.mysql.com/) database server running and a database with at least one table > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Set up Prisma ORM As a first step, navigate into your project directory that contains the `package.json` file. Next, add the Prisma CLI as a development dependency to your project: ```terminal copy npm install prisma --save-dev ``` :::note If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-planetscale Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). :::tip If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. ::: ## Prerequisites In order to successfully complete this guide, you need: - an existing Node.js project with a `package.json` - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [PlanetScale](https://planetscale.com/) database server running and a database with at least one table > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Set up Prisma ORM As a first step, navigate into your project directory that contains the `package.json` file. Next, add the Prisma CLI as a development dependency to your project: ```terminal copy npm install prisma --save-dev ``` :::note If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). :::tip If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. ::: ## Prerequisites In order to successfully complete this guide, you need: - an existing Node.js project with a `package.json` - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - a [PostgreSQL](https://www.postgresql.org/) database server running and a database with at least one table > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Set up Prisma ORM As a first step, navigate into your project directory that contains the `package.json` file. Next, add the Prisma CLI as a development dependency to your project: ```terminal copy npm install prisma --save-dev ``` :::note If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Relational databases URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-sqlserver Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). :::tip If you're migrating to Prisma ORM from another ORM, see our [Migrate from TypeORM](/guides/migrate-from-typeorm) or [Migrate from Sequelize](/guides/migrate-from-sequelize) migration guides. ::: ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - A [Microsoft SQL Server](https://learn.microsoft.com/en-us/sql/?view=sql-server-ver16) database - [Microsoft SQL Server on Linux for Docker](/orm/overview/databases/sql-server/sql-server-docker) - [Microsoft SQL Server on Windows (local)](/orm/overview/databases/sql-server/sql-server-local) > See [System requirements](/orm/reference/system-requirements) for exact version requirements. Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). ## Set up Prisma ORM As a first step, navigate into your project directory that contains the `package.json` file. Next, add the Prisma CLI as a development dependency to your project: ```terminal copy npm install prisma --save-dev ``` :::note If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # Connect your database (MongoDB) URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/mongodb/connect-your-database-node-mongodb ## Connecting your database To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "mongodb" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`: ```bash file=.env showLineNumbers DATABASE_URL="mongodb+srv://test:test@cluster0.ns1yp.mongodb.net/myFirstDatabase" ``` You now need to adjust the connection URL to point to your own database. The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For MongoDB, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines mongodb://USERNAME:PASSWORD@HOST:PORT/DATABASE ``` Here's a short explanation of each component: - `USERNAME`: The name of your database user - `PASSWORD`: The password for your database user - `HOST`: The host where a [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) (or [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos/#mongodb-binary-bin.mongos)) instance is running - `PORT`: The port where your database server is running (typically `27017` for MongoDB) - `DATABASE`: The name of the database. Note that if you're using MongoDB Atlas, you need to manually append the database name to the connection URL because the environment link from MongoDB Atlas doesn't contain it. ## Troubleshooting ### `Error in connector: SCRAM failure: Authentication failed.` If you see the `Error in connector: SCRAM failure: Authentication failed.` error message, you can specify the source database for the authentication by [adding](https://github.com/prisma/prisma/discussions/9994#discussioncomment-1562283) `?authSource=admin` to the end of the connection string. ### `Raw query failed. Error code 8000 (AtlasError): empty database name not allowed.` If you see the `Raw query failed. Code: unknown. Message: Kind: Command failed: Error code 8000 (AtlasError): empty database name not allowed.` error message, be sure to append the database name to the database URL. You can find more info in this [GitHub issue](https://github.com/prisma/docs/issues/5562). --- # Connect your database (MongoDB) URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/mongodb/connect-your-database-typescript-mongodb ## Connecting your database To connect your database, you need to set the `url` field of the `datasource` block in your Prisma schema to your database [connection URL](/orm/reference/connection-urls): ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "mongodb" url = env("DATABASE_URL") } ``` In this case, the `url` is [set via an environment variable](/orm/more/development-environment/environment-variables) which is defined in `.env`: ```bash file=.env showLineNumbers DATABASE_URL="mongodb+srv://test:test@cluster0.ns1yp.mongodb.net/myFirstDatabase" ``` You now need to adjust the connection URL to point to your own database. The [format of the connection URL](/orm/reference/connection-urls) for your database depends on the database you use. For MongoDB, it looks as follows (the parts spelled all-uppercased are _placeholders_ for your specific connection details): ```no-lines mongodb://USERNAME:PASSWORD@HOST:PORT/DATABASE ``` Here's a short explanation of each component: - `USERNAME`: The name of your database user - `PASSWORD`: The password for your database user - `HOST`: The host where a [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) (or [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos/#mongodb-binary-bin.mongos)) instance is running - `PORT`: The port where your database server is running (typically `27017` for MongoDB) - `DATABASE`: The name of the database. Note that if you're using MongoDB Atlas, you need to manually append the database name to the connection URL because the environment link from MongoDB Atlas doesn't contain it. ## Troubleshooting ### `Error in connector: SCRAM failure: Authentication failed.` If you see the `Error in connector: SCRAM failure: Authentication failed.` error message, you can specify the source database for the authentication by [adding](https://github.com/prisma/prisma/discussions/9994#discussioncomment-1562283) `?authSource=admin` to the end of the connection string. ### `Raw query failed. Error code 8000 (AtlasError): empty database name not allowed.` If you see the `Raw query failed. Code: unknown. Message: Kind: Command failed: Error code 8000 (AtlasError): empty database name not allowed.` error message, be sure to append the database name to the database URL. You can find more info in this [GitHub issue](https://github.com/prisma/docs/issues/5562). --- # Introspection URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/mongodb/introspection-node-mongodb # Introspection Prisma ORM introspects a MongoDB schema by sampling the data stored in the given database and inferring the schema of that data. For the purposes of illustrating introspection, this guide will help you setup a MongoDB from scratch. But if you have a MongoDB database already, feel free to jump to [Initializing Prisma ORM](#initializing-prisma-orm) in your project. ## Setting up your Database To see this in action, first create a `blog` database with 2 collections: `User` and `Post`. We recommend [MongoDB Compass](https://www.mongodb.com/products/tools/compass) for setting this up: ![Create a blog database using Compass](/img/getting-started/1-create-database.jpg) First, add a user to our `User` collection: ![Create a user within the User collection](/img/getting-started/2-create-user.jpg) Next, add some posts to our `Post` collection. It's important that the ObjectID in `userId` matches the user you created above. ![Create some posts within the Post collection](/img/getting-started/3-create-posts.jpg) ## Initializing Prisma ORM Now that you have a MongoDB database, the next step is to create a new project and initialize Prisma ORM: ```terminal copy mkdir blog cd blog npm init -y npm install -D prisma npx prisma init --datasource-provider mongodb --output ../generated/prisma ``` Initializing Prisma ORM will create a `prisma/schema.prisma` file like the following: ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } ``` Next you'll need to adjust your `.env` file to point the `DATABASE_URL` to your MongoDB database ## Introspecting MongoDB with Prisma ORM You're now ready to introspect. Run the following command to introspect your database: ```terminal copy npx prisma db pull ``` This command introspects our database and writes the inferred schema into your `prisma/schema.prisma` file: ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId title String userId String @db.ObjectId } model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String } ``` ## Tweaking the Schema To be able to join data using Prisma Client, you can add the [`@relation`](/orm/reference/prisma-schema-reference#relation) attributes to our models: ```prisma file=prisma/schema.prisma highlight=14;add|20;add showLineNumbers datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId title String userId String @db.ObjectId //add-next-line user User @relation(fields: [userId], references: [id]) } model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String //add-next-line posts Post[] } ``` :::tip We're actively working on MongoDB introspection. Provide feedback for this feature in [this issue](https://github.com/prisma/prisma/issues/8241). ::: And with that, you're ready to generate Prisma Client. --- # Introspection URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/mongodb/introspection-typescript-mongodb # Introspection Prisma ORM introspects a MongoDB schema by sampling the data stored in the given database and inferring the schema of that data. For the purposes of illustrating introspection, this guide will help you setup a MongoDB from scratch. But if you have a MongoDB database already, feel free to jump to [Initializing Prisma ORM](#initializing-prisma-orm) in your project. ## Setting up your Database To see this in action, first create a `blog` database with 2 collections: `User` and `Post`. We recommend [MongoDB Compass](https://www.mongodb.com/products/tools/compass) for setting this up: ![Create a blog database using Compass](/img/getting-started/1-create-database.jpg) First, add a user to our `User` collection: ![Create a user within the User collection](/img/getting-started/2-create-user.jpg) Next, add some posts to our `Post` collection. It's important that the ObjectID in `userId` matches the user you created above. ![Create some posts within the Post collection](/img/getting-started/3-create-posts.jpg) ## Initializing Prisma ORM Now that you have a MongoDB database, the next step is to create a new project and initialize Prisma ORM: ```terminal copy mkdir blog cd blog npm init -y npm install -D prisma npx prisma init --datasource-provider mongodb --output ../generated/prisma ``` Initializing Prisma ORM will create a `prisma/schema.prisma` file. Edit this file to use MongoDB: ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } ``` Next you'll need to adjust your `.env` file to point the `DATABASE_URL` to your MongoDB database ## Introspecting MongoDB with Prisma ORM You're now ready to introspect. Run the following command to introspect your database: ```terminal copy npx prisma db pull ``` This command introspects our database and writes the inferred schema into your `prisma/schema.prisma` file: ```prisma file=prisma/schema.prisma showLineNumbers datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId title String userId String @db.ObjectId } model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String } ``` ## Tweaking the Schema To be able to join data using Prisma Client, you can add the [`@relation`](/orm/reference/prisma-schema-reference#relation) attributes to our models: ```prisma file=prisma/schema.prisma highlight=14;add|20;add showLineNumbers datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId title String userId String @db.ObjectId //add-next-line user User @relation(fields: [userId], references: [id]) } model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String //add-next-line posts Post[] } ``` :::tip We're actively working on MongoDB introspection. Provide feedback for this feature in [this issue](https://github.com/prisma/prisma/issues/8241). ::: And with that, you're ready to generate Prisma Client. --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/mongodb/install-prisma-client-node-mongodb ## Install and generate Prisma Client To get started with Prisma Client, you need to install the `@prisma/client` package: ```terminal copy npm install @prisma/client ``` The install command invokes `prisma generate` for you which reads your Prisma schema and generates a version of Prisma Client that is _tailored_ to your models. ![Install and generate Prisma Client](/img/getting-started/prisma-client-install-and-generate.png) Whenever you make changes to your Prisma schema in the future, you manually need to invoke `prisma generate` in order to accommodate the changes in your Prisma Client API. --- # Install Prisma Client URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/mongodb/install-prisma-client-typescript-mongodb ## Install and generate Prisma Client To get started with Prisma Client, you need to install the `@prisma/client` package: ```terminal copy npm install @prisma/client ``` The install command invokes `prisma generate` for you which reads your Prisma schema and generates a version of Prisma Client that is _tailored_ to your models. ![Install and generate Prisma Client](/img/getting-started/prisma-client-install-and-generate.png) Whenever you make changes to your Prisma schema in the future, you manually need to invoke `prisma generate` in order to accommodate the changes in your Prisma Client API. --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/mongodb/querying-the-database-node-mongodb ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). Create a new file named `index.js` and add the following code to it: ```js file=index.js copy const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Connect to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```js file=index.js showLineNumbers async function main() { - // ... you will write your Prisma Client queries here //add-start + const allUsers = await prisma.user.findMany() + console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy node index.js ``` If you introspected an existing database with records, the query should return an array of JavaScript objects. ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post`, `User` and `Comment` tables. Adjust the `main` function to send a `create` query to the database: ```js file=index.js copy showLineNumbers async function main() { await prisma.user.create({ data: { name: 'Rich', email: 'hello@prisma.com', posts: { create: { title: 'My first post', body: 'Lots of really interesting stuff', slug: 'my-first-post', }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, }, }) console.dir(allUsers, { depth: null }) } ``` This code creates a new `User` record together with a new `Post` using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the other one via the `Post.author` ↔ `User.posts` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` relations on the returned `User` objects. Run the code with this command: ```terminal copy node index.js ``` The output should look similar to this: ```json no-lines [ { id: '60cc9b0e001e3bfd00a6eddf', email: 'hello@prisma.com', name: 'Rich', posts: [ { id: '60cc9bad005059d6007f45dd', slug: 'my-first-post', title: 'My first post', body: 'Lots of really interesting stuff', userId: '60cc9b0e001e3bfd00a6eddf', }, ], }, ] ``` The query added new records to the `User` and the `Post` collections: The `id` field in the Prisma schema maps to `_id` in the underlying MongoDB database. **User** collection | **\_id** | **email** | **name** | | :------------------------- | :------------------- | :------- | | `60cc9b0e001e3bfd00a6eddf` | `"hello@prisma.com"` | `"Rich"` | **Post** collection | **\_id** | **createdAt** | **title** | **content** | **published** | **authorId** | | :------------------------- | :------------------------- | :---------------- | :--------------------------------- | :------------ | :------------------------- | | `60cc9bad005059d6007f45dd` | `2020-03-21T16:45:01.246Z` | `"My first post"` | `Lots of really interesting stuff` | `false` | `60cc9b0e001e3bfd00a6eddf` | > **Note**: The unique identifier in the `authorId` document field on `Post` reference the `_id` document field in the `User` collection, meaning the `_id` value `60cc9b0e001e3bfd00a6eddf` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll add a couple of comments to the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```js file=index.js copy async function main() { await prisma.post.update({ where: { slug: 'my-first-post', }, data: { comments: { createMany: { data: [ { comment: 'Great post!' }, { comment: "Can't wait to read more!" }, ], }, }, }, }) const posts = await prisma.post.findMany({ include: { comments: true, }, }) console.dir(posts, { depth: Infinity }) } ``` Now run the code using the same command as before: ```terminal copy node index.js ``` You will see the following output: ```json no-lines [ { id: '60cc9bad005059d6007f45dd', slug: 'my-first-post', title: 'My first post', body: 'Lots of really interesting stuff', userId: '60cc9b0e001e3bfd00a6eddf', comments: [ { id: '60cca420008a21d800578793', postId: '60cca40300af8bf000f6ca99', comment: 'Great post!', }, { id: '60cca420008a21d800578794', postId: '60cca40300af8bf000f6ca99', comment: "Can't wait to try this!", }, ], }, ] ``` Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Querying the database URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/mongodb/querying-the-database-typescript-mongodb ## Write your first query with Prisma Client Now that you have generated Prisma Client, you can start writing queries to read and write data in your database. For the purpose of this guide, you'll use a plain Node.js script to explore some basic features of Prisma Client. If you're building a REST API, you can use Prisma Client in your route handlers to read and write data in the database based on incoming HTTP requests. If you're building a GraphQL API, you can use Prisma Client in your resolvers to read and write data in the database based on incoming queries and mutations. For the purpose of this guide however, you'll just create a plain Node.js script to learn how to send queries to your database using Prisma Client. Once you have an understanding of how the API works, you can start integrating it into your actual application code (e.g. REST route handlers or GraphQL resolvers). Create a new file named `index.ts` and add the following code to it: ```js file=index.ts copy import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { // ... you will write your Prisma Client queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Here's a quick overview of the different parts of the code snippet: 1. Import the `PrismaClient` constructor from the `@prisma/client` node module 1. Instantiate `PrismaClient` 1. Define an `async` function named `main` to send queries to the database 1. Connect to the database 1. Call the `main` function 1. Close the database connections when the script terminates Inside the `main` function, add the following query to read all `User` records from the database and print the result: ```ts file=index.ts showLineNumbers async function main() { // ... you will write your Prisma Client queries here //add-start + const allUsers = await prisma.user.findMany() + console.log(allUsers) //add-end } ``` Now run the code with this command: ```terminal copy npx tsx index.ts ``` If you introspected an existing database with records, the query should return an array of JavaScript objects. ## Write data into the database The `findMany` query you used in the previous section only _reads_ data from the database (although it was still empty). In this section, you'll learn how to write a query to _write_ new records into the `Post`, `User` and `Comment` tables. Adjust the `main` function to send a `create` query to the database: ```ts file=index.ts copy showLineNumbers async function main() { await prisma.user.create({ data: { name: 'Rich', email: 'hello@prisma.com', posts: { create: { title: 'My first post', body: 'Lots of really interesting stuff', slug: 'my-first-post', }, }, }, }) const allUsers = await prisma.user.findMany({ include: { posts: true, }, }) console.dir(allUsers, { depth: null }) } ``` This code creates a new `User` record together with a new `Post` using a [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) query. The `User` record is connected to the other one via the `Post.author` ↔ `User.posts` [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) respectively. Notice that you're passing the [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) option to `findMany` which tells Prisma Client to include the `posts` relations on the returned `User` objects. Run the code with this command: ```terminal copy npx tsx index.ts ``` The output should look similar to this: ```json no-lines [ { id: '60cc9b0e001e3bfd00a6eddf', email: 'hello@prisma.com', name: 'Rich', posts: [ { id: '60cc9bad005059d6007f45dd', slug: 'my-first-post', title: 'My first post', body: 'Lots of really interesting stuff', userId: '60cc9b0e001e3bfd00a6eddf', }, ], }, ] ``` Also note that `allUsers` is _statically typed_ thanks to [Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types). You can observe the type by hovering over the `allUsers` variable in your editor. It should be typed as follows: ```ts no-lines showLineNumbers const allUsers: (User & { posts: Post[] })[] export type Post = { id: number title: string body: string | null published: boolean authorId: number | null } ``` The query added new records to the `User` and the `Post` collections: The `id` field in the Prisma schema maps to `_id` in the underlying MongoDB database. **User** collection | **\_id** | **email** | **name** | | :------------------------- | :------------------- | :------- | | `60cc9b0e001e3bfd00a6eddf` | `"hello@prisma.com"` | `"Rich"` | **Post** collection | **\_id** | **createdAt** | **title** | **content** | **published** | **authorId** | | :------------------------- | :------------------------- | :---------------- | :--------------------------------- | :------------ | :------------------------- | | `60cc9bad005059d6007f45dd` | `2020-03-21T16:45:01.246Z` | `"My first post"` | `Lots of really interesting stuff` | `false` | `60cc9b0e001e3bfd00a6eddf` | > **Note**: The unique identifier in the `authorId` document field on `Post` reference the `_id` document field in the `User` collection, meaning the `_id` value `60cc9b0e001e3bfd00a6eddf` column therefore refers to the first (and only) `User` record in the database. Before moving on to the next section, you'll add a couple of comments to the `Post` record you just created using an `update` query. Adjust the `main` function as follows: ```ts file=index.ts copy showLineNumbers async function main() { await prisma.post.update({ where: { slug: 'my-first-post', }, data: { comments: { createMany: { data: [ { comment: 'Great post!' }, { comment: "Can't wait to read more!" }, ], }, }, }, }) const posts = await prisma.post.findMany({ include: { comments: true, }, }) console.dir(posts, { depth: Infinity }) } ``` Now run the code using the same command as before: ```terminal copy npx tsx index.ts ``` You will see the following output: ```json no-lines [ { id: '60cc9bad005059d6007f45dd', slug: 'my-first-post', title: 'My first post', body: 'Lots of really interesting stuff', userId: '60cc9b0e001e3bfd00a6eddf', comments: [ { id: '60cca420008a21d800578793', postId: '60cca40300af8bf000f6ca99', comment: 'Great post!', }, { id: '60cca420008a21d800578794', postId: '60cca40300af8bf000f6ca99', comment: "Can't wait to try this!", }, ], }, ] ``` Fantastic, you just wrote new data into your database for the first time using Prisma Client 🚀 --- # Next steps URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/mongodb/next-steps This section lists a number of potential next steps you can now take from here. Feel free to explore these or read the [Introduction](/orm/overview/introduction/what-is-prisma) page to get a high-level overview of Prisma ORM. ### Continue exploring the Prisma Client API You can send a variety of queries with the Prisma Client API. Check out the [API reference](/orm/prisma-client) and use your existing database setup from this guide to try them out. :::tip You can use your editor's auto-completion feature to learn about the different API calls and the arguments it takes. Auto-completion is commonly invoked by hitting CTRL+SPACE on your keyboard. :::
Expand for more Prisma Client API examples Here are a few suggestions for a number of more queries you can send with Prisma Client: **Filter all `Post` records that contain `"hello"`** ```js const filteredPosts = await prisma.post.findMany({ where: { OR: [{ title: { contains: 'hello' } }, { body: { contains: 'hello' } }], }, }) ``` **Create a new `Post` record and connect it to an existing `User` record** ```js const post = await prisma.post.create({ data: { title: 'Join us for Prisma Day 2020', slug: 'prisma-day-2020', body: 'A conference on modern application development and databases.', user: { connect: { email: 'hello@prisma.com' }, }, }, }) ``` **Use the fluent relations API to retrieve the `Post` records of a `User` by traversing the relations** ```js const user = await prisma.comment .findUnique({ where: { id: '60ff4e9500acc65700ebf470' }, }) .post() .user() ``` **Delete a `User` record** ```js const deletedUser = await prisma.user.delete({ where: { email: 'sarah@prisma.io' }, }) ```
### Build an app with Prisma ORM The Prisma blog features comprehensive tutorials about Prisma ORM, check out our latest ones: - [Build a fullstack app with Next.js](https://www.youtube.com/watch?v=QXxy8Uv1LnQ&ab_channel=ByteGrad) - [Build a fullstack app with Remix](https://www.prisma.io/blog/fullstack-remix-prisma-mongodb-1-7D0BfTXBmB6r) (5 parts, including videos) - [Build a REST API with NestJS](https://www.prisma.io/blog/nestjs-prisma-rest-api-7D056s1BmOL0) ### Explore the data in Prisma Studio Prisma Studio is a visual editor for the data in your database. Run `npx prisma studio` in your terminal. ### Try a Prisma ORM example The [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository contains a number of ready-to-run examples: | Demo | Stack | Description | | :------------------------------------------------------------------------------------------------------------------ | :----------- | --------------------------------------------------------------------------------------------------- | | [`nextjs`](https://pris.ly/e/orm/nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app | | [`nextjs-graphql`](https://pris.ly/e/ts/graphql-nextjs) | Fullstack | Simple [Next.js](https://nextjs.org/) app (React) with a GraphQL API | | [`graphql-nexus`](https://pris.ly/e/ts/graphql-nexus) | Backend only | GraphQL server based on [`@apollo/server`](https://www.apollographql.com/docs/apollo-server) | | [`express`](https://pris.ly/e/ts/rest-express) | Backend only | Simple REST API with Express.JS | | [`grpc`](https://pris.ly/e/ts/grpc) | Backend only | Simple gRPC API | --- # MongoDB URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/mongodb-node-mongodb Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). If you're migrating to Prisma ORM from Mongoose, see our [Migrate from Mongoose guide](/guides/migrate-from-mongoose). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - Access to a MongoDB 4.2+ server with a replica set deployment. We recommend using [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). The MongoDB database connector uses transactions to support nested writes. Transactions **requires** a [replica set](https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/) deployment. The easiest way to deploy a replica set is with [Atlas](https://www.mongodb.com/docs/atlas/getting-started/). It's free to get started. Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). > See [System requirements](/orm/reference/system-requirements) for exact version requirements. ## Set up Prisma ORM As a first step, navigate into it your project directory that contains the `package.json` file. Next, add the Prisma CLI as a development dependency to your project: ```terminal copy npm install prisma --save-dev ``` :::note If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- # MongoDB URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/mongodb-typescript-mongodb Learn how to add Prisma ORM to an existing Node.js or TypeScript project by connecting it to your database and generating a Prisma Client for database access. The following tutorial introduces you to [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Introspection](/orm/prisma-schema/introspection). If you're migrating to Prisma ORM from Mongoose, see our [Migrate from Mongoose guide](/guides/migrate-from-mongoose). ## Prerequisites In order to successfully complete this guide, you need: - [Node.js](https://nodejs.org/en/) installed on your machine (see [system requirements](/orm/reference/system-requirements) for officially supported versions) - Access to a MongoDB 4.2+ server with a replica set deployment. We recommend using [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). The MongoDB database connector uses transactions to support nested writes. Transactions **requires** a [replica set](https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/) deployment. The easiest way to deploy a replica set is with [Atlas](https://www.mongodb.com/docs/atlas/getting-started/). It's free to get started. Make sure you have your database [connection URL](/orm/reference/connection-urls) (that includes your authentication credentials) at hand! If you don't have a database server running and just want to explore Prisma ORM, check out the [Quickstart](/getting-started/quickstart-sqlite). > See [System requirements](/orm/reference/system-requirements) for exact version requirements. ## Set up Prisma ORM As a first step, navigate into it your project directory that contains the `package.json` file. Next, add the Prisma CLI as a development dependency to your project: ```terminal copy npm install prisma --save-dev ``` :::note If your project contains multiple directories with `package.json` files (e.g., `frontend`, `backend`, etc.), note that Prisma ORM is specifically designed for use in the API/backend layer. To set up Prisma, navigate to the appropriate backend directory containing the relevant `package.json` file and configure Prisma there. ::: import PrismaInitPartial from './_prisma-init-partial.mdx' --- import CodeBlock from '@theme/CodeBlock'; You can now invoke the Prisma CLI by prefixing it with `npx`: ```terminal npx prisma ``` :::info See [installation instructions](/orm/tools/prisma-cli#installation) to learn how to install Prisma ORM using a different package manager. ::: Next, set up your Prisma ORM project by creating your [Prisma Schema](/orm/prisma-schema) file with the following command: {`npx prisma init --datasource-provider ${props.datasource.toLowerCase()} --output ../generated/prisma`} This command does a few things: - Creates a new directory called `prisma` that contains a file called `schema.prisma`, which contains the Prisma Schema with your database connection variable and schema models. - Sets the `datasource` to {props.datasource} and the output to a custom location, respectively. - Creates the [`.env` file](/orm/more/development-environment/environment-variables) in the root directory of the project, which is used for defining environment variables (such as your database connection) :::info Using version control? If you're using version control, like git, we recommend you add a line to your `.gitignore` in order to exclude the generated client from your application. In this example, we want to exclude the `generated/prisma` directory. ```code file=.gitignore //add-start generated/prisma/ //add-end ``` ::: Note that the default schema created by `prisma init` uses PostgreSQL as the `provider`. If you didn't specify a provider with the `datasource-provider` option, you need to edit the `datasource` block to use the {props.datasource.toLowerCase()} provider instead: {`datasource db { //edit-next-line provider = "${props.datasource.toLowerCase()}" url = env("DATABASE_URL") }`} --- # Add to existing project URL: https://www.prisma.io/docs/getting-started/setup-prisma/add-to-existing-project/index Include Prisma ORM in an existing project with the following documentation, which explains some core concepts as it guides you through integrating Prisma ORM into your workflow. ## In this section --- # Set up Prisma ORM URL: https://www.prisma.io/docs/getting-started/setup-prisma/index Start from scratch or add Prisma ORM to an existing project. The following tutorials introduce you to the [Prisma CLI](/orm/tools/prisma-cli), [Prisma Client](/orm/prisma-client), and [Prisma Migrate](/orm/prisma-migrate). ## In this section --- # From the CLI URL: https://www.prisma.io/docs/getting-started/prisma-postgres/from-the-cli This page provides a step-by-step guide for Prisma Postgres after setting it up with `prisma init --db`: 1. Set up a TypeScript app with Prisma ORM 1. Migrate the schema of your database 1. Query your database from TypeScript ## Prerequisites This guide assumes you set up [Prisma Postgres](/postgres) instance with `prisma init --db`: ```terminal npx prisma@latest init --db ``` ```code no-copy wrap Success! Your Prisma Postgres database is ready ✅ We created an initial schema.prisma file and a .env file with your DATABASE_URL environment variable already set. --- Next steps --- Go to https://pris.ly/ppg-init for detailed instructions. 1. Define your database schema Open the schema.prisma file and define your first models. Check the docs if you need inspiration: https://pris.ly/ppg-init 2. Apply migrations Run the following command to create and apply a migration: npx prisma migrate dev --name init 3. Manage your data View and edit your data locally by running this command: npx prisma studio ... or online in Console: https://console.prisma.io/cliwxim5p005xqh0g3mvqpyak/cm6kw97t801ijzhvfwz4a0my3/cm6kw97ta01ikzhvf965vresv/studio 4. Send queries from your app To access your database from a JavaScript/TypeScript app, you need to use Prisma ORM. Go here for step-by-step instructions: https://pris.ly/ppg-init ``` Once this command terminated: - You're logged into Prisma Data Platform. - A new Prisma Postgres instance was created. - The `prisma/` folder was created with an empty `schema.prisma` file. - The `DATABASE_URL` env var was set in a `.env` file. ## 1. Organize your project directory :::note If you ran the `prisma init --db` command inside a folder where you want your project to live, you can skip this step and [proceed to the next section](/getting-started/prisma-postgres/from-the-cli#2-set-up-your-project). ::: If you ran the command outside your intended project directory (e.g., in your home folder or another location), you need to move the generated `prisma` folder and the `.env` file into a dedicated project directory. Create a new folder (e.g. `hello-prisma`) where you want your project to live and move the necessary files into it: ```terminal mkdir hello-prisma mv .env ./hello-prisma/ mv prisma ./hello-prisma/ ``` Navigate into your project folder: ```terminal cd ./hello-prisma ``` Now that your project is in the correct location, continue with the setup. ## 2. Set up your project ### 2.1. Set up TypeScript Initialize a TypeScript project and add the Prisma CLI as a development dependency: ```terminal npm init -y npm install typescript tsx @types/node --save-dev ``` This creates a `package.json` file with an initial setup for your TypeScript app. Next, initialize TypeScript with a `tsconfig.json` file in the project: ```terminal npx tsc --init ``` ### 2.2. Set up Prisma ORM Install the required dependencies to use Prisma Postgres: ```terminal npm install prisma --save-dev npm install @prisma/extension-accelerate ``` ### 2.3. Create a TypeScript script Create an `index.ts` file in the root directory, this will be used to query your application with Prisma ORM: ```terminal touch index.ts ``` ## 3. Migrate the database schema Update your `prisma/schema.prisma` file to include a simple `User` model: ```prisma file=prisma/schema.prisma model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int } ``` After adding the models, migrate your database using [Prisma Migrate](/orm/prisma-migrate): ```terminal npx prisma migrate dev --name init ``` ## 4. Send queries with Prisma ORM Paste the following boilerplate into `index.ts`: ```ts file=index.ts import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' const prisma = new PrismaClient().$extends(withAccelerate()) async function main() { // ... you will write your Prisma ORM queries here } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` This code contains a `main` function that's invoked at the end of the script. It also instantiates `PrismaClient` which you'll use to send queries to your database. ### 4.1. Create a new `User` record Let's start with a small query to create a new `User` record in the database and log the resulting object to the console. Add the following code to your `index.ts` file: ```ts file=index.ts import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' const prisma = new PrismaClient().$extends(withAccelerate()) async function main() { // add-start const user = await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', }, }) console.log(user) // add-end } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Next, execute the script with the following command: ```terminal npx tsx index.ts ``` ```code no-copy { id: 1, email: 'alice@prisma.io', name: 'Alice' } ``` Great job, you just created your first database record with Prisma Postgres! 🎉 ### 4.2. Retrieve all `User` records Prisma ORM offers various queries to read data from your database. In this section, you'll use the `findMany` query that returns _all_ the records in the database for a given model. Delete the previous Prisma ORM query and add the new `findMany` query instead: ```ts file=index.ts import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' const prisma = new PrismaClient().$extends(withAccelerate()) async function main() { // add-start const users = await prisma.user.findMany() console.log(users) // add-end } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Execute the script again: ```terminal npx tsx index.ts ``` ```code no-copy [{ id: 1, email: 'alice@prisma.io', name: 'Alice' }] ``` Notice how the single `User` object is now enclosed with square brackets in the console. That's because the `findMany` returned an array with a single object inside. ### 4.3. Explore relation queries One of the main features of Prisma ORM is the ease of working with [relations](/orm/prisma-schema/data-model/relations). In this section, you'll learn how to create a `User` and a `Post` record in a nested write query. Afterwards, you'll see how you can retrieve the relation from the database using the `include` option. First, adjust your script to include the nested query: ```ts file=index.ts import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' const prisma = new PrismaClient().$extends(withAccelerate()) async function main() { // add-start const user = await prisma.user.create({ data: { name: 'Bob', email: 'bob@prisma.io', posts: { create: [ { title: 'Hello World', published: true }, { title: 'My second post', content: 'This is still a draft' } ], }, }, }) console.log(user) // add-end } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Run the query by executing the script again: ```terminal npx tsx index.ts ``` ```code no-copy { id: 2, email: 'bob@prisma.io', name: 'Bob' } ``` In order to also retrieve the `Post` records that belong to a `User`, you can use the `include` option via the `posts` relation field: ```ts file=index.ts import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' const prisma = new PrismaClient().$extends(withAccelerate()) async function main() { // add-start const usersWithPosts = await prisma.user.findMany({ include: { posts: true, }, }) console.dir(usersWithPosts, { depth: null }) // add-end } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` Run the script again to see the results of the nested read query: ```terminal npx tsx index.ts ``` ```code no-copy [ { id: 1, email: 'alice@prisma.io', name: 'Alice', posts: [] }, { id: 2, email: 'bob@prisma.io', name: 'Bob', posts: [ { id: 1, title: 'Hello World', content: null, published: true, authorId: 2 }, { id: 2, title: 'My second post', content: 'This is still a draft', published: false, authorId: 2 } ] } ] ``` This time, you're seeing two `User` objects being printed. Both of them have a `posts` field (which is empty for `"Alice"` and populated with two `Post` objects for `"Bob"`) that represents the `Post` records associated with them. ## Next steps You just got your feet wet with a basic Prisma Postgres setup. If you want to explore more complex queries, such as adding caching functionality, check out the official [Quickstart](/getting-started/quickstart-prismaPostgres). ### View and edit data in Prisma Studio Prisma ORM comes with a built-in GUI to view and edit the data in your database. You can open it using the following command: ```terminal npx prisma studio ``` With Prisma Postgres, you can also directly use Prisma Studio inside the [Console](https://console.prisma.io) by selecting the **Studio** tab in your project. ### Build a fullstack app with Next.js Learn how to use Prisma Postgres in a fullstack app: - [Build a fullstack app with Next.js 15](/guides/nextjs) - [Next.js 15 example app](https://github.com/prisma/nextjs-prisma-postgres-demo) (including authentication) ### Explore ready-to-run examples Check out the [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository on GitHub to see how Prisma ORM can be used with your favorite library. The repo contains examples with Express, NestJS, GraphQL as well as fullstack examples with Next.js and Vue.js, and a lot more. These examples use SQLite by default but you can follow the instructions in the project README to switch to Prisma Postgres in a few simple steps. --- # Import from existing database URL: https://www.prisma.io/docs/getting-started/prisma-postgres/import-from-existing-database-postgresql This guide provides step-by-step instructions for importing data from an existing PostgreSQL database into Prisma Postgres. You can accomplish this migration in three steps: 1. Create a new Prisma Postgres database. 1. Export your existing data via `pg_dump`. 1. Import the previously exported data into Prisma Postgres via `pg_restore`. In the third step, you will be using the [TCP tunnel](/postgres/tcp-tunnel) to securely connect to your Prisma Postgres database during to run `pg_restore`. ## Prerequisites - The connection URL to your existing PostgreSQL database - A [Prisma Data Platform](https://console.prisma.io) account - Node.js 18+ installed - PostgreSQL CLI Tools (`pg_dump`, `pg_restore`) for creating and restoring backups ## 1. Create a new Prisma Postgres database Follow these steps to create a new Prisma Postgres database: 1. Log in to [Prisma Data Platform](https://console.prisma.io/) and open the Console. 1. In a [workspace](/platform/about#workspace) of your choice, click the **New project** button. 1. Type a name for your project in the **Name** field, e.g. **hello-ppg**. 1. In the **Prisma Postgres** section, click the **Get started** button. 1. In the **Region** dropdown, select the region that's closest to your current location, e.g. **US East (N. Virginia)**. 1. Click the **Create project** button. Once your database was provisioned, find your Prisma Postgres connection URL in the **Set up database access** section and save it for later, you'll need it in step 3. ## 2. Export data from your existing database In this step, you're going to export the data from your existing database and store it in a `.bak` file on your local machine. Make sure to have the connection URL for your existing database ready, it should be [structured](/orm/overview/databases/postgresql#connection-url) like this: ```no-copy postgresql://USER:PASSWORD@HOST:PORT/DATABASE ``` Expand below for provider-specific instructions that help you determine the right connection string:
Neon
- Make sure to select non-pooled connection string by switching off the **Connection pooling** toggle. - The `sslmode` has to be set to `require` and appended to your Neon database url for the command to work. - The connection URL should look similar to this: ```no-copy postgresql://USER:PASSWORD@YOUR-NEON-HOST/DATABASE?sslmode=require ```
Supabase - Use a database connection URL that uses [Supavisor session mode](https://supabase.com/docs/guides/database/connecting-to-postgres#supavisor-session-mode). - The connection URL should look similar to this: ```no-copy postgres://postgres.apbkobhfnmcqqzqeeqss:[YOUR-PASSWORD]@aws-0-ca-central-1.pooler.supabase.com:5432/postgres ```
Next, run the following command to export the data of your PostgreSQL database (replace the `__DATABASE_URL__` placeholder with your actual database connection URL): ```terminal pg_dump \ -Fc \ -v \ -d __DATABASE_URL__ \ -n public \ -f db_dump.bak ``` Here's a quick overview of the CLI options that were used for this command: - `-Fc`: Uses the custom format for backups, recommended for `pg_restore` - `-v`: Runs `pg_dump` in verbose mode - `-d`: Specifies the database connection string - `-n`: Specifies the target PostgreSQL schema - `-f`: Specifies the output name for the backup file Running this command will create a backup file named `db_dump.bak` which you will use to restore the data into your Prisma Postgres database in the next step. ## 3. Import data into Prisma Postgres In this step, you'll use the [TCP tunnel](/postgres/tcp-tunnel) to connect to your Prisma Postgres instance and import data via `pg_restore`. You'll also need the Prisma Postgres connection URL from step 1, it should look similar to this: ```no-copy prisma+postgres://accelerate.prisma-data.net/?api_key=ey... ``` If you already have a `.env` file in your current directory with `DATABASE_URL` set, the tunnel CLI will automatically pick it up, no need to manually export it. However, if you haven't set up a `.env` file, you'll need to set the `DATABASE_URL` environment variable explicitly. To set the environment variable, open your terminal and set the `DATABASE_URL` environment variable to the value of your Prisma Postgres database URL (replace the `__API_KEY__` placeholder with the API key of your actual database connection URL): ```terminal export DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=__API_KEY__" ``` :::note If you explicitly set `DATABASE_URL` in your terminal, that value will take precedence over the one in your `.env` file. ::: Next, start the TCP tunnel: ```terminal npx @prisma/ppg-tunnel --host 127.0.0.1 --port 5433 ``` ```code no-copy wrap Prisma Postgres auth proxy listening on 127.0.0.1:5433 🚀 Your connection is authenticated using your Prisma Postgres API key. ... ============================== hostname: 127.0.0.1 port: 5433 username: password: ============================== ``` :::note Keep your current terminal window or tab open so that the tunnel process continues running and the connection remains open. ::: Now, use the `db_dump.bak` backup file from the previous step to restore data into your Prisma Postgres database with the `pg_restore` command: ```terminal PGSSLMODE=disable \ pg_restore \ -h 127.0.0.1 \ -p 5433 \ -v \ -d postgres \ ./db_dump.bak \ && echo "-complete-" ``` :::note You don't need to provide username and password credentials to this command because the TCP tunnel already authenticated you via the API key in your Prisma Postgres connection URL. ::: You now successfully imported the data from your your existing PostgreSQL database into Prisma Postgres 🎉 To validate that the import worked, you can use [Prisma Studio](/postgres/tooling#viewing-and-editing-data-in-prisma-studio). Either open it in the [Platform Console](https://console.prisma.io) by clicking the **Studio** tab in the left-hand sidenav in your project or run this command to launch Prisma Studio locally: ```terminal npx prisma studio ``` ## 4. Update your application code to query Prisma Postgres ### Scenario A: You are already using Prisma ORM If you already using Prisma ORM, the only things you need to do are: - add the Prisma Accelerate extension to your project - update the database connection URL and re-generate Prisma Client #### 4.A.1. Add the Prisma Accelerate extension Th Prisma Accelerate extension is [required](/postgres/overview#using-the-client-extension-for-prisma-accelerate-required) when using Prisma Postgres. If you are not currently using Prisma Accelerate with Prisma ORM, go through the following steps to make Prisma ORM work with Prisma Postgres. First, install the `@prisma/extension-accelerate` package in your project: ```terminal npm install @prisma/extension-accelerate ``` Then, add the extension to your Prisma Client instance: ```ts import { withAccelerate } from '@prisma/extension-accelerate' const prisma = new PrismaClient().$extends(withAccelerate()) ``` #### 4.A.2. Update the database connection URL The database connection URL is configured via the `url` of the `datasource` block in your `schema.prisma` file. Most commonly, it is set via an environment variable called `DATABASE_URL`: ```prisma file=schema.prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` The next steps assumes that you're a `.env` file to set the `DATABASE_URL` environment variable (if that's not the case, you can set the environment variable in your preferred way). Open `.env` and update the value for the `DATABASE_URL` environment variable to match your Prisma Postgres connection URL, looking similar to this: ```bash DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=__API_KEY__" ``` As a last step, you need to re-generate Prisma Client for so that the updated environment variables takes effect and your queries go to Prisma Postgres going forward: ``` npx prisma generate --no-engine ``` Once this is done, you can run your application and it should work as before. ### Scenario B: You are not yet using Prisma ORM If you are not yet using Prisma ORM, you'll need to go through the following steps to use Prisma Postgres from your application: 1. Install the Prisma CLI in your project 1. Introspect the database to generate a Prisma schema 1. Generate Prisma Client 1. Update the queries in your application to use Prisma ORM You can find the detailed step-by-step instructions for this process in this guide: [Add Prisma ORM to an existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql). --- # Import from existing database URL: https://www.prisma.io/docs/getting-started/prisma-postgres/import-from-existing-database-mysql This guide provides step-by-step instructions for importing data from an existing MySQL database into Prisma Postgres. You can accomplish this migration in four steps: 1. Create a new Prisma Postgres database. 1. Connect directly to a Prisma Postgres instance using the [`@prisma/ppg-tunnel` package](https://www.npmjs.com/package/@prisma/ppg-tunnel). 1. Migrate your MySQL data to Prisma Postgres using [pgloader](https://pgloader.io/). 1. Configure your Prisma project for Prisma Postgres. ## Prerequisites - The connection URL to your existing MySQL database. - A [Prisma Data Platform](https://console.prisma.io) account. - Node.js 18+ installed. - [pgloader](https://pgloader.io/) installed. We recommend attempting this migration in a separate git development branch. ## 1. Create a new Prisma Postgres database Follow these steps to create a new Prisma Postgres database: 1. Log in to [Prisma Data Platform](https://console.prisma.io/) and open the Console. 1. In a [workspace](/platform/about#workspace) of your choice, click the **New project** button. 1. Type a name for your project in the **Name** field, e.g. **hello-ppg**. 1. In the **Prisma Postgres** section, click the **Get started** button. 1. In the **Region** dropdown, select the region that's closest to your current location, e.g. **US East (N. Virginia)**. 1. Click the **Create project** button. Once your database was provisioned, find your Prisma Postgres connection URL in the **Set up database access** section and save it for later, you'll need it in the next step. ## 2. Connect directly to a Prisma Postgres instance In this step, you'll use a secure [TCP tunnel](/postgres/tcp-tunnel) to connect to your Prisma Postgres instance. You'll need the Prisma Postgres connection URL from [step 1](/getting-started/prisma-postgres/import-from-existing-database-mysql#1-create-a-new-prisma-postgres-database): ```no-copy prisma+postgres://accelerate.prisma-data.net/?api_key=ey... ``` If you already have a `.env` file in your current directory with `DATABASE_URL` set, the tunnel CLI will automatically pick it up, no need to manually export it. However, if you haven't set up a `.env` file, you'll need to set the `DATABASE_URL` environment variable explicitly. To set the environment variable, open your terminal and set the `DATABASE_URL` environment variable to the value of your Prisma Postgres database URL (replace the `__API_KEY__` placeholder with the API key of your actual database connection URL): ```terminal export DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=__API_KEY__" ``` :::note If you explicitly set `DATABASE_URL` in your terminal, that value will take precedence over the one in your `.env` file. ::: Next, start the TCP tunnel using the `@prisma/ppg-tunnel` package, by executing the following command: ```terminal npx @prisma/ppg-tunnel --host 127.0.0.1 --port 5433 ``` :::note You can [specify a different host and port](/postgres/tcp-tunnel#customizing-host-and-port) by providing your own host and port values using the `--port` and `--host` flags. Just be sure to use the same host and port values consistently throughout the guide. ::: ```code no-copy wrap Prisma Postgres auth proxy listening on 127.0.0.1:5433 🚀 Your connection is authenticated using your Prisma Postgres API key. ... ============================== hostname: 127.0.0.1 port: 5433 username: password: ============================== ``` :::note *Keep your current terminal window or tab open* so that the tunnel process continues running and the connection remains open. ::: ## 3. Migrate your MySQL data to Prisma Postgres using pgloader Now that you have an active connection to your Prisma Postgres instance, you'll use pgloader to export data from your MySQL database to Prisma Postgres. Open a separate terminal window and create a `config.load` file: ```terminal touch config.load ``` Open the `config.load` file in your preferred text editor and copy-paste the following configuration: ```text file=config.load LOAD DATABASE FROM mysql://username:password@host:PORT/database_name INTO postgresql://user:password@127.0.0.1:5433/postgres WITH quote identifiers, -- preserve table/column name case by quoting them include drop, create tables, create indexes, reset sequences ALTER SCHEMA 'database_name' RENAME TO 'public'; ``` Make sure to update the following details in the `config.load` file: - `FROM` url (MySQL database URL): - Replace `username`, `password`, `host`, `PORT`, and `database_name` with the actual connection details for your MySQL database. - Ensure that your connection string includes `useSSL=true` if SSL is required, for example: `mysql://username:password@host:PORT/database_name?useSSL=true`. Note that when using PlanetScale, appending `sslaccept=strict` will not work. - `INTO` url (Postgres database URL): - Update this with your TCP tunnel details if you’re using a custom `host` and `port` (in this example, it’s `127.0.0.1` and port `5433` for consistency). - Update the `database_name` in `ALTER SCHEMA 'database_name' RENAME TO 'public';` to exactly match the `database_name` in your MySQL connection string. After saving the configuration file with your updated credentials, in the same terminal window, execute the following command: ```terminal pgloader config.load ``` You should see a log similar to this, which confirms the successful migration of your data: ```terminal LOG report summary reset table name errors rows bytes total time ------------------------- --------- --------- --------- -------------- fetch meta data 0 9 2.546s Create Schemas 0 0 0.325s Create SQL Types 0 0 0.635s Create tables 0 6 5.695s Set Table OIDs 0 3 0.328s ------------------------- --------- --------- --------- -------------- public.post 0 8 0.5 kB 4.255s public."user" 0 4 0.1 kB 2.775s public._prisma_migrations 0 1 0.2 kB 4.278s ------------------------- --------- --------- --------- -------------- COPY Threads Completion 0 4 5.095s Index Build Completion 0 5 9.601s Create Indexes 0 5 4.116s Reset Sequences 0 2 4.540s Primary Keys 0 3 2.917s Create Foreign Keys 0 1 1.121s Create Triggers 0 0 0.651s Install Comments 0 0 0.000s ------------------------- --------- --------- --------- -------------- Total import time ✓ 13 0.8 kB 28.042s ``` If you see output like this, it means your data has been successfully exported to your Prisma Postgres instance. :::note You also can use [Prisma Studio](/postgres/tooling#viewing-and-editing-data-in-prisma-studio) and verify whether the migration was successful: ```terminal npx prisma studio ``` ::: ## 4. Configure your Prisma project for Prisma Postgres After migrating your data, you need to set up your Prisma project to work with Prisma Postgres. The steps differ depending on whether you were already using Prisma ORM. ### If you **were not** previously using Prisma ORM Initialize Prisma in your project by running `npx prisma init` in your project directory. This creates a `prisma` folder with a `schema.prisma` file and `.env` file (if not already present). In the generated `.env` file, update `DATABASE_URL` to match your Prisma Postgres connection string that you received in [step 1](/getting-started/prisma-postgres/import-from-existing-database-mysql#1-create-a-new-prisma-postgres-database): ```terminal file=.env no-copy DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=__API_KEY__" ``` [Introspect](/orm/prisma-schema/introspection) your newly migrated database by running: ```terminal npx prisma db pull ``` This command updates your `schema.prisma` file with models representing your migrated tables, so you can start using [Prisma Client](/orm/prisma-client) to query your data or [Prisma Migrate](/orm/prisma-migrate/getting-started) to manage future changes. Congratulations! You've successfully migrated your MySQL database to Prisma Postgres and configured your Prisma project. Your migration tutorial is now complete. :::note For a comprehensive guide on getting started with Prisma and Prisma Postgres, see [start from scratch with Prisma and Prisma Postgres](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-prismaPostgres). ::: ### If you **were** already using Prisma ORM In your `schema.prisma` file, change the `provider` in the `datasource` block from `mysql` to `postgresql`: ```prisma file=schema.prisma datasource db { // delete-start provider = "mysql" // delete-end // add-start provider = "postgres" // add-end url = env("DATABASE_URL") } ``` In the generated `.env` file, update `DATABASE_URL` to match your new Prisma Postgres connection string that you received in [step 1](/getting-started/prisma-postgres/import-from-existing-database-mysql#1-create-a-new-prisma-postgres-database): ```terminal file=.env no-copy DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=__API_KEY__" ``` Introspect your newly migrated Prisma Postgres database and generate Prisma Client: ```terminal npx prisma db pull ``` This command refreshes your Prisma models based on the new database schema. If you were using [Prisma Migrate](/orm/prisma-migrate/getting-started) before: - Delete your existing `migrations` folder in the `prisma` directory. - [Baseline your database](/orm/prisma-migrate/workflows/baselining#baselining-a-database) to begin creating new migrations. Congratulations! You've successfully migrated your MySQL database to Prisma Postgres and configured your Prisma project. Your migration tutorial is now complete. If you encounter any issues during the migration, please don't hesitate to reach out to us on [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=conclusion) or via [X](https://pris.ly/x?utm_source=docs&utm_medium=conclusion). --- # Upgrade from Early Access URL: https://www.prisma.io/docs/getting-started/prisma-postgres/upgrade-from-early-access This guide shows you how to migrate your Prisma Postgres Early Access (EA) database to the now official Prisma Postgres General Availability (GA) database. Prisma Postgres Early Access was introduced to allow early adopters to test Prisma’s new managed PostgreSQL service. As we move to GA, it's crucial to safely migrate data from your EA database to the new GA database. Prisma will _not_ automatically migrate your data to ensure its integrity. Instead, this process must be done manually. You can accomplish this in three main steps: 1. Back up your EA database via `pg_dump`. 2. Create a new GA database. 3. Import your backup into the GA database via `pg_restore`. We will be using the [`@prisma/ppg-tunnel`](https://www.npmjs.com/package/@prisma/ppg-tunnel) package to securely connect to both databases. This tool sets up a secure proxy tunnel, eliminating the need for manual credential handling. You can learn more about **Prisma Postgres** on [this page](/postgres). ## Prerequisites Before you begin, make sure you have: - **Node.js** installed (version 16 or higher). - **PostgreSQL CLI Tools** (`pg_dump`, `pg_restore`) for creating and restoring backups. - A **Database connection string** for your Prisma Postgres database. To create and restore backups, ensure you have the PostgreSQL command-line tools installed. Run the following commands based on your operating system: ```terminal brew install postgresql@16 which pg_dump which pg_restore ``` ```terminal # Download from the official PostgreSQL website: # https://www.postgresql.org/download/windows/ # During installation, select "Command Line Tools". # Then verify with: where pg_dump where pg_restore ``` ```terminal sudo apt-get update sudo apt-get install postgresql-client-16 which pg_dump which pg_restore ``` :::tip If you installed PostgreSQL but still see a “command not found” error for pg_dump or pg_restore, ensure your installation directory is in your system’s PATH environment variable. ::: :::note Please make sure that you are installing Postgresql version 16. Other versions may cause errors during the backup and restore process. ::: ## Option A: Interactive approach This approach is recommended if you prefer a guided, one-command solution. In this mode, the `@prisma/ppg-tunnel` CLI: 1. Prompts you for your Early Access (EA) database API key (or `DATABASE_URL`). 2. Uses `pg_dump` behind the scenes to back up your EA database to a file in the current directory. 3. Prompts you for your new GA database URL or API Key. 4. Uses `pg_restore` to import the backup file into your GA database. Interactive mode does not accept any CLI arguments or read API keys from the environment. You must provide them interactively. ### Steps 1. Open a terminal and run: ```bash npx @prisma/ppg-tunnel migrate-from-ea ``` 2. When prompted, paste your Early Access database key or connection string. The CLI will create a `.bak` file in the current directory. 3. When prompted again, paste your GA database key or connection string. The CLI will automatically restore the .bak file into the new GA database. 4. Once complete, connect with your favorite Database IDE to verify your data in the GA database. ## Option B: Manual backup-and-restore approach If you prefer or need finer control over the migration process (or to pass environment variables directly), follow these manual steps. The migration involves three main parts: 1. Back up your EA database via `pg_dump`. 2. Create a new GA database. 3. Import your backup into the GA database via `pg_restore`. We will still be using the `@prisma/ppg-tunnel` package to securely connect to both databases. ## 1. Back up the EA database ### 1.1. Connecting to the EA database directly with `@prisma/ppg-tunnel` In your terminal, run `npx @prisma/ppg-tunnel` to establish a secure tunnel to your Early Access database. If you already have a `.env` file in your current directory with `DATABASE_URL` set, the tunnel CLI will automatically pick it up—no need to manually export it. However, if you haven't set up a `.env` file, you'll need to set the `DATABASE_URL` environment variable explicitly. To set environment variable (with your actual EA database URL): ```bash export DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI..." ``` :::note If you explicitly set `DATABASE_URL` in your terminal, that value will take precedence over the one in your `.env` file. ::: Run the tunnel: ```bash npx @prisma/ppg-tunnel --host 127.0.0.1 --port 5432 ``` You should see output similar to: ```cmd Prisma Postgres auth proxy listening on 127.0.0.1:5432 🚀 Your connection is authenticated using your Prisma Postgres API key. ... ============================== hostname: 127.0.0.1 port: 5432 username: password: ============================== ``` :::note Please note that the port you will see in your output will be a randomly assigned port which may be different from the one mentioned here. Also, Keep this terminal window open so the tunnel remains active! If you close it, the tunnel disconnects. ::: Copy the port number from the terminal output, you’ll need it in the next step for the `pg_dump` command. ### 1.2. Creating the Backup with `pg_dump` With the tunnel running, you can now dump the EA database by running the following command: ```bash PGSSLMODE=disable \ pg_dump \ -h 127.0.0.1 \ -p 5432 \ -Fc \ -v \ -d postgres \ -f ./mydatabase.bak \ && echo "-complete-" ``` `PGSSLMODE=disable` indicates SSL is not required locally because the tunnel already encrypts the connection. ``` `-h` is the host (127.0.0.1) `-p` is the port, which should match the one from the tunnel output. `-Fc` uses the custom format for backups, recommended for pg_restore. `-d` postgres is the default database name used in Prisma Postgres. `-f` ./mydatabase.bak specifies the backup file name and location. `-v` runs pg_dump in verbose mode. ``` This should create your backup file named `mydatabase.bak` in the current directory. We will use this backup file for importing in next steps. ## 2. Create a new GA database Next, create your GA (General Availability) database: 1. Visit [console.prisma.io](https://console.prisma.io) and sign in (or create an account). 2. Create a Prisma Postgres database in the region of your choice. 3. Copy the Database URL for later use. Prisma Postgres GA uses PostgreSQL 17, so you’ll be restoring your EA backup into this new environment. ## 3. Import the backup into the GA database ### 3.1. Connecting to the GA Database with `@prisma/ppg-tunnel` Open a new terminal (or stop the previous tunnel) and connect to your GA database: Set environment variables for the new GA database: ```bash export DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI..." ``` Run the tunnel: ```bash npx @prisma/ppg-tunnel --host 127.0.0.1 --port 5432 ``` You should see output similar to: ```cmd Prisma Postgres auth proxy listening on 127.0.0.1:52604 🚀 Your connection is authenticated using your Prisma Postgres API key. ... ============================== hostname: 127.0.0.1 port: 52604 username: password: ============================== ``` :::note Again, keep this tunnel process running to maintain the connection! ::: ### 3.2. Restoring the Backup with `pg_restore` Use the backup file from **Step 1** to restore data into your GA database with `pg_restore` by running this command: ```bash PGSSLMODE=disable \ pg_restore \ -h 127.0.0.1 \ -p 5432 \ -v \ -d postgres \ ./mydatabase.bak \ && echo "-complete-" ``` Also, in this case the database name is `postgres`. You can replace it with your desired database name. It does not matter what you name your database as you will be able to use Prisma Postgres as usual. The backup file name (mydatabase.bak in our example) should match the one you created in Step 1. This command restores the backup into the GA database. If successful, you should see `-complete-` in the terminal. ## Next steps Connect with your favorite Database IDE or Prisma Client to confirm all tables, rows, and schemas match your old EA environment. Congratulations! You have successfully migrated your Prisma Postgres Early Access database to Prisma Postgres GA. If you encounter any issues, please reach out to our [support team](https://www.prisma.io/support). --- # Prisma Postgres URL: https://www.prisma.io/docs/getting-started/prisma-postgres/index ## In this section --- # Get Started URL: https://www.prisma.io/docs/getting-started/index import { Bolt, BorderBox, BoxTitle, Inspect, Database, Grid, LinkCard, List, SignalStream, PrismaPostgres, SquareLogo, } from '@site/src/components/GettingStarted'; Get started Welcome 👋 Explore our products that make it easy to build and scale data-driven applications: [**Prisma ORM**](/orm/overview/introduction/what-is-prisma) is a next-generation Node.js and TypeScript ORM that unlocks a new level of developer experience when working with databases thanks to its intuitive data model, automated migrations, type-safety & auto-completion. [**Prisma Optimize**](/optimize/) helps you analyze queries, generate insights, and provides recommendations to make your database queries faster. [**Prisma Accelerate**](/accelerate) is a global database cache with scalable connection pooling to make your queries fast. [**Prisma Postgres**](/postgres) is a managed PostgreSQL service that gives you an _always-on_ database with _pay-as-you-go_ pricing. ## Prisma ORM Add Prisma ORM to your application in a few minutes to start modeling your data, run schema migrations and query your database. ### The easiest way to get started with Prisma _Explore all Prisma products at once._ ### Explore quickly with a SQLite database _These options don't require you to have your own database running._ ### Choose an option to get started with your own database _Select one of these options if you want to connect Prisma ORM to your own database._

Set up Prisma ORM from scratch with your favorite database and learn basic workflows like data modeling, querying, and migrations.

Get started with Prisma ORM and your existing database by introspecting your database schema and learn how to query your database.

## Prisma Accelerate Make your database queries faster by scaling your database connections and caching database results at the edge with Prisma Accelerate.
## Prisma Optimize Make your database queries faster by using the insights and recommendations generated by Prisma Optimize. --- # What is Prisma ORM? URL: https://www.prisma.io/docs/orm/overview/introduction/what-is-prisma Prisma ORM is an [open-source](https://github.com/prisma/prisma) next-generation ORM. It consists of the following parts: - **Prisma Client**: Auto-generated and type-safe query builder for Node.js & TypeScript - **Prisma Migrate**: Migration system - **Prisma Studio**: GUI to view and edit data in your database. :::info **Prisma Studio** is the only part of Prisma ORM that is not open source. You can only run Prisma Studio locally. ::: Prisma Client can be used in _any_ Node.js (supported versions) or TypeScript backend application (including serverless applications and microservices). This can be a [REST API](/orm/overview/prisma-in-your-stack/rest), a [GraphQL API](/orm/overview/prisma-in-your-stack/graphql), a gRPC API, or anything else that needs a database.
## How does Prisma ORM work? ### The Prisma schema Every project that uses a tool from the Prisma ORM toolkit starts with a [Prisma schema](/orm/prisma-schema). The Prisma schema allows developers to define their _application models_ in an intuitive data modeling language. It also contains the connection to a database and defines a _generator_: ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User? @relation(fields: [authorId], references: [id]) authorId Int? } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } ``` ```prisma datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId title String content String? published Boolean @default(false) author User? @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId } model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique name String? posts Post[] } ``` > **Note**: The Prisma schema has powerful data modeling features. For example, it allows you to define "Prisma-level" [relation fields](/orm/prisma-schema/data-model/relations) which will make it easier to work with [relations in the Prisma Client API](/orm/prisma-client/queries/relation-queries). In the case above, the `posts` field on `User` is defined only on "Prisma-level", meaning it does not manifest as a foreign key in the underlying database. In this schema, you configure three things: - **Data source**: Specifies your database connection (via an environment variable) - **Generator**: Indicates that you want to generate Prisma Client - **Data model**: Defines your application models ### The Prisma schema data model On this page, the focus is on the data model. You can learn more about [Data sources](/orm/prisma-schema/overview/data-sources) and [Generators](/orm/prisma-schema/overview/generators) on the respective docs pages. #### Functions of Prisma schema data models The data model is a collection of [models](/orm/prisma-schema/data-model/models#defining-models). A model has two major functions: - Represent a table in relational databases or a collection in MongoDB - Provide the foundation for the queries in the Prisma Client API #### Getting a data model There are two major workflows for "getting" a data model into your Prisma schema: - Manually writing the data model and mapping it to the database with [Prisma Migrate](/orm/prisma-migrate) - Generating the data model by [introspecting](/orm/prisma-schema/introspection) a database Once the data model is defined, you can [generate Prisma Client](/orm/prisma-client/setup-and-configuration/generating-prisma-client) which will expose CRUD and more queries for the defined models. If you're using TypeScript, you'll get full type-safety for all queries (even when only retrieving the subsets of a model's fields). ### Accessing your database with Prisma Client #### Generating Prisma Client The first step when using Prisma Client is installing the `@prisma/client` and `prisma` npm packages: ```terminal npm install @prisma/client npm install prisma --save-dev ``` Then, you can run `prisma generate`: ```terminal npx prisma generate ``` The `prisma generate` command reads your Prisma schema and _generates_ Prisma Client code. The code is [generated into the `node_modules/.prisma/client` folder by default](/orm/prisma-client/setup-and-configuration/generating-prisma-client#the-prismaclient-npm-package). After you change your data model, you'll need to manually re-generate Prisma Client by running `prisma generate` to ensure the code inside `node_modules/.prisma/client` gets updated. #### Using Prisma Client to send queries to your database Once Prisma Client has been generated, you can import it in your code and send queries to your database. This is what the setup code looks like. ##### Import and instantiate Prisma Client ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() ``` ```js const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() ``` Now you can start sending queries via the generated Prisma Client API, here are a few sample queries. Note that all Prisma Client queries return _plain old JavaScript objects_. Learn more about the available operations in the [Prisma Client API reference](/orm/prisma-client). ##### Retrieve all `User` records from the database ```ts // Run inside `async` function const allUsers = await prisma.user.findMany() ``` ##### Include the `posts` relation on each returned `User` object ```ts // Run inside `async` function const allUsers = await prisma.user.findMany({ include: { posts: true }, }) ``` ##### Filter all `Post` records that contain `"prisma"` ```ts // Run inside `async` function const filteredPosts = await prisma.post.findMany({ where: { OR: [ { title: { contains: 'prisma' } }, { content: { contains: 'prisma' } }, ], }, }) ``` ##### Create a new `User` and a new `Post` record in the same query ```ts // Run inside `async` function const user = await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', posts: { create: { title: 'Join us for Prisma Day 2020' }, }, }, }) ``` ##### Update an existing `Post` record ```ts // Run inside `async` function const post = await prisma.post.update({ where: { id: 42 }, data: { published: true }, }) ``` #### Usage with TypeScript Note that when using TypeScript, the result of this query will be _statically typed_ so that you can't accidentally access a property that doesn't exist (and any typos are caught at compile-time). Learn more about leveraging Prisma Client's generated types on the [Advanced usage of generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types) page in the docs. ## Typical Prisma ORM workflows As mentioned above, there are two ways for "getting" your data model into the Prisma schema. Depending on which approach you choose, your main Prisma ORM workflow might look different. ### Prisma Migrate With **Prisma Migrate**, Prisma ORM's integrated database migration tool, the workflow looks as follows: 1. Manually adjust your [Prisma schema data model](/orm/prisma-schema/data-model/models) 1. Migrate your development database using the `prisma migrate dev` CLI command 1. Use Prisma Client in your application code to access your database ![Typical workflow with Prisma Migrate](/img/orm/prisma-migrate-development-workflow.png) To learn more about the Prisma Migrate workflow, see: - [Deploying database changes with Prisma Migrate](/orm/prisma-client/deployment/deploy-database-changes-with-prisma-migrate) * [Developing with Prisma Migrate](/orm/prisma-migrate) ### SQL migrations and introspection If for some reason, you can not or do not want to use Prisma Migrate, you can still use introspection to update your Prisma schema from your database schema. The typical workflow when using **SQL migrations and introspection** is slightly different: 1. Manually adjust your database schema using SQL or a third-party migration tool 1. (Re-)introspect your database 1. Optionally [(re-)configure your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names)) 1. (Re-)generate Prisma Client 1. Use Prisma Client in your application code to access your database ![Introspect workflow](/img/orm/prisma-evolve-app-workflow.png) To learn more about the introspection workflow, please refer the [introspection section](/orm/prisma-schema/introspection). --- # Why Prisma ORM? URL: https://www.prisma.io/docs/orm/overview/introduction/why-prisma On this page, you'll learn about the motivation for Prisma ORM and how it compares to other database tools like traditional ORMs and SQL query builders. Working with relational databases is a major bottleneck in application development. Debugging SQL queries or complex ORM objects often consume hours of development time. Prisma ORM makes it easy for developers to reason about their database queries by providing a clean and type-safe API for submitting database queries which returns _plain old JavaScript objects_. ## TLDR Prisma ORM's main goal is to make application developers more productive when working with databases. Here are a few examples of how Prisma ORM achieves this: - **Thinking in objects** instead of mapping relational data - **Queries not classes** to avoid complex model objects - **Single source of truth** for database and application models - **Healthy constraints** that prevent common pitfalls and anti-patterns - **An abstraction that makes the right thing easy** ("pit of success") - **Type-safe database queries** that can be validated at compile time - **Less boilerplate** so developers can focus on the important parts of their app - **Auto-completion in code editors** instead of needing to look up documentation The remaining parts of this page discuss how Prisma ORM compares to existing database tools. ## Problems with SQL, traditional ORMs and other database tools The main problem with the database tools that currently exist in the Node.js and TypeScript ecosystem is that they require a major tradeoff between _productivity_ and _control_. ![Productivity vs Control in ORMs, SQL query builders, and SQL](./node-js-db-tools-tradeoffs.png) ### Raw SQL: Full control, low productivity With raw SQL (e.g. using the native [`pg`](https://node-postgres.com/) or [`mysql`](https://github.com/mysqljs/mysql) Node.js database drivers) you have full control over your database operations. However, productivity suffers as sending plain SQL strings to the database is cumbersome and comes with a lot of overhead (manual connection handling, repetitive boilerplate, ...). Another major issue with this approach is that you don't get any type safety for your query results. Of course, you can type the results manually but this is a huge amount of work and requires major refactorings each time you change your database schema or queries to keep the typings in sync. Furthermore, submitting SQL queries as plain strings means you don't get any autocompletion in your editors. ### SQL query builders: High control, medium productivity A common solution that retains a high level of control and provides better productivity is to use a SQL query builder (e.g. [knex.js](https://knexjs.org/)). These sort of tools provide a programmatic abstraction to construct SQL queries. The biggest drawback with SQL query builders is that application developers still need to think about their data in terms of SQL. This incurs a cognitive and practical cost of translating relational data into objects. Another issue is that it's too easy to shoot yourself in the foot if you don't know exactly what you're doing in your SQL queries. ### Traditional ORMs: Less control, better productivity Traditional ORMs abstract away from SQL by letting you _define your application models as classes_, these classes are mapped to tables in the database. > "Object relational mappers" (ORMs) exist to bridge the gap between the programmers' friend (the object), and the database's primitive (the relation). The reasons for these differing models are as much cultural as functional: programmers like objects because they encapsulate the state of a single thing in a running program. Databases like relations because they better suit whole-dataset constraints and efficient access patterns for the entire dataset. > > [The Troublesome Active Record Pattern, Cal Paterson (2020)](https://calpaterson.com/activerecord.html) You can then read and write data by calling methods on the instances of your model classes. This is way more convenient and comes closer to the mental model developers have when thinking about their data. So, what's the catch? > ORM represents a quagmire which starts well, gets more complicated as time passes, and before long entraps its users in a commitment that has no clear demarcation point, no clear win conditions, and no clear exit strategy. > > [The Vietnam of Computer Science, Ted Neward (2006)](https://blog.codinghorror.com/object-relational-mapping-is-the-vietnam-of-computer-science/) As an application developer, the mental model you have for your data is that of an _object_. The mental model for data in SQL on the other hand are _tables_. The divide between these two different representations of data is often referred to as the [object-relational impedance mismatch](https://en.wikipedia.org/wiki/Object-relational_impedance_mismatch). The object-relational impedance mismatch also is a major reason why many developers don't like working with traditional ORMs. As an example, consider how data is organized and relationships are handled with each approach: - **Relational databases**: Data is typically normalized (flat) and uses foreign keys to link across entities. The entities then need to be JOINed to manifest the actual relationships. - **Object-oriented**: Objects can be deeply nested structures where you can traverse relationships simply by using dot notation. This alludes to one of the major pitfalls with traditional ORMs: While they make it _seem_ that you can simply traverse relationships using familiar dot notation, under the hood the ORM generates SQL JOINs which are expensive and have the potential to drastically slow down your application (one symptom of this is the [n+1 problem](https://stackoverflow.com/questions/97197/what-is-the-n1-selects-problem-in-orm-object-relational-mapping)). To conclude: The appeal of traditional ORMs is the premise of abstracting away the relational model and thinking about your data purely in terms of objects. While the premise is great, it's based on the wrong assumption that relational data can easily be mapped to objects which leads to lots of complications and pitfalls. ## Application developers should care about data – not SQL Despite being developed in the 1970s(!), SQL has stood the test of time in an impressive manner. However, with the advancement and modernization of developers tools, it's worth asking if SQL really is the best abstraction for application developers to work with? After all, **developers should only care about the _data_ they need to implement a feature** and not spend time figuring out complicated SQL queries or massaging query results to fit their needs. There's another argument to be made against SQL in application development. The power of SQL can be a blessing if you know exactly what you're doing, but its complexity can be a curse. There are a lot of [anti-patterns](https://www.slideshare.net/billkarwin/sql-antipatterns-strike-back) and pitfalls that even experienced SQL users struggle to anticipate, often at the cost of performance and hours of debugging time. Developers should be able to ask for the data they need instead of having to worry about "doing the right thing" in their SQL queries. They should be using an abstraction that makes the right decisions for them. This can mean that the abstraction imposes certain "healthy" constraints that prevent developers from making mistakes. ## Prisma ORM makes developers productive Prisma ORM's main goal is to make application developers more productive when working with databases. Considering the tradeoff between productivity and control again, this is how Prisma ORM fits in: ![Prisma ORM makes developers productive](./prisma-makes-devs-productive.png) --- # Should you use Prisma ORM? URL: https://www.prisma.io/docs/orm/overview/introduction/should-you-use-prisma Prisma ORM is a new kind of ORM that - like any other tool - comes with its own tradeoffs. This page explains when Prisma ORM would be a good fit, and provides alternatives for other scenarios. ## Prisma ORM likely _is_ a good fit for you if ... ### ... you are building a server-side application that talks to a database This is the main use case for Prisma ORM. Server-side applications typically are API servers that expose data operations via technologies like REST, GraphQL or gRPC. They are commonly built as microservices or monolithic apps and deployed via long-running servers or serverless functions. Prisma ORM is a great fit for all of these application and deployment models. Refer to the full list of databases (relational, NoSQL, and NewSQL) that Prisma ORM [supports](/orm/reference/supported-databases). ### ... you care about productivity and developer experience Productivity and developer experience are core to how we're building our tools. We're looking to build developer-friendly abstractions for tasks that are complex, error-prone and time-consuming when performed manually. No matter if you're a SQL newcomer or veteran, Prisma ORM will give you a significant productivity boost for the most common database workflows. Here are a couple of the guiding principles and general practices we apply when designing and building our tools: - [make the right thing easy](https://jason.energy/right-thing-easy-thing/) - [pit of success](https://blog.codinghorror.com/falling-into-the-pit-of-success/) - offer intelligent autocompletion where possible - build powerful editor extensions (e.g. for [VS Code](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma)) - go the extra mile to achieve full type-safety ### ... you are working in a team Prisma ORM shines especially when used in collaborative environments. The declarative [Prisma schema](/orm/prisma-schema) provides an overview of the current state of the database that's easy to understand for everyone. This is a major improvement to traditional workflows where developers have to dig through migration files to understand the current table structure. [Prisma Client](/orm/prisma-client)'s minimal API surface enables developers to pick it up quickly without much learning overhead, so onboarding new developers to a team becomes a lot smoother. The [Prisma Migrate](/orm/prisma-migrate) workflows are designed in a way to cover database schema changes in collaborative environments. From the initial schema creation up to the point of deploying schema changes to production and resolving conflicts that were introduced by parallel modifications, Prisma Migrate has you covered. ### ... you want a tool that holistically covers your database workflows Prisma ORM is a lot more than "just another ORM". We are building a database toolkit that covers the daily workflows of application developers that interact with databases. A few examples are: - querying (with [Prisma Client](/orm/prisma-client)) - data modeling (in the [Prisma schema](/orm/prisma-schema)) - migrations (with [Prisma Migrate](/orm/prisma-migrate)) - prototyping (via [`prisma db push`](/orm/reference/prisma-cli-reference#db-push)) - seeding (via [`prisma db seed`](/orm/reference/prisma-cli-reference#db-seed)) - visual viewing and editing (with [Prisma Studio](https://www.prisma.io/studio)) ### ... you value type-safety Prisma ORM is the only _fully_ type-safe ORM in the TypeScript ecosystem. The generated Prisma Client ensures typed query results even for partial queries and relations. You can learn more about this in the [type-safety comparison with TypeORM](/orm/more/comparisons/prisma-and-typeorm#type-safety). ### ... you want to write raw, type-safe SQL In addition to the intuitive, higher-level query API, Prisma ORM also offers a way for you to [write raw SQL with full type safety](https://www.prisma.io/blog/announcing-typedsql-make-your-raw-sql-queries-type-safe-with-prisma-orm). ### ... you want an ORM with a transparent development process, proper maintenance & support Development of Prisma ORM's open source tools is happening in the open. Most of it happens directly on GitHub in the main [`prisma/prisma`](https://github.com/prisma/prisma) repo: - issues and PRs in our repos are triaged and prioritized (usually within 1-2 days) - new [releases](https://github.com/prisma/prisma/releases) with new features and improvements are issued every three weeks - we have a dedicated support team that responds to questions in [GitHub Discussions](https://github.com/prisma/prisma/discussions) ### ... you want to be part of an awesome community Prisma has a lively [community](https://www.prisma.io/community) that you can find on [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=inline_text). We also regularly host Meetups, conferences and other developer-focused events. Join us! ## Prisma ORM likely is _not_ a good fit for you if ... ### ... you need _full_ control over all database queries Prisma ORM is an abstraction. As such, an inherent tradeoff of Prisma ORM is a reduced amount of control in exchange for higher productivity. This means, the [Prisma Client API](/orm/prisma-client) might have less capabilities in some scenarios than you get with plain SQL. If your application has requirements for database queries that Prisma ORM does not provide and the workarounds are too costly, you might be better off with a tool that allows you to exercise full control over your database operations using plain SQL. > **Note**: If you can work around a certain limitation but still would like to see an improvement in the way how Prisma ORM handles the situation, we encourage you to create a [feature request](https://github.com/prisma/prisma/issues/new?assignees=&labels=&template=feature_request.md&title=) on GitHub so that our Product and Engineering teams can look into it. _Alternatives_: SQL drivers (e.g. [`node-postgres`](https://node-postgres.com/), [`mysql`](https://github.com/mysqljs/mysql), [`sqlite3`](https://github.com/TryGhost/node-sqlite3), ...) ### ... you do not want to write any code for your backend If you don't want to write any code for your backend and just be able to generate your API server and the database out-of-the-box, you might rather choose a Backend-as-a-Service (BaaS) for your project. With a BaaS, you can typically configure your data model via a high-level API (e.g. [GraphQL SDL](https://www.prisma.io/blog/graphql-sdl-schema-definition-language-6755bcb9ce51)) or a visual editor. Based on this data model, the BaaS generates a CRUD API and provisions a database for you. With this setup, you typically don't have control over the infrastructure the API server and database are running on. With Prisma ORM, you are building the backend yourself using Node.js or TypeScript. This means you'll have to do a lot more coding work compared to using a BaaS. The benefit of this approach is that you have full flexibility for building, deploying, scaling and maintaining your backend and are not dependent on 3rd party software for a crucial part of your stack. _Alternatives_: [AWS AppSync](https://aws.amazon.com/appsync/), [8base](https://www.8base.com/), [Nhost](https://nhost.io/), [Supabase](https://supabase.com/), [Firebase](https://firebase.google.com/), [Amplication](https://amplication.com/) ### ... you want a CRUD GraphQL API without writing any code While tools like the [`nexus-plugin-prisma`](https://nexusjs.org/docs/plugins/prisma/overview) and [`typegraphql-prisma`](https://github.com/MichalLytek/typegraphql-prisma#readme) allow you to quickly generate CRUD operations for your Prisma ORM models in a GraphQL API, these approaches still require you to set up your GraphQL server manually and do some work to expose GraphQL queries and mutations for the models defined in your Prisma schema. If you want to get a GraphQL endpoint for your database out-of-the box, other tools might be better suited for your use case. _Alternatives_: [Hasura](https://hasura.io/), [Postgraphile](https://www.graphile.org/postgraphile/) --- # Data modeling URL: https://www.prisma.io/docs/orm/overview/introduction/data-modeling ## What is data modeling? The term _data modeling_ refers to the **process of defining the shape and structure of the objects in an application**, these objects are often called "application models". In relational databases (like PostgreSQL), they are stored in _tables_ . When using document databases (like MongoDB), they are stored in _collections_. Depending on the domain of your application, the models will be different. For example, if you're writing a blogging application, you might have models such as _blog_, _author_, _article_. When writing a car-sharing app, you probably have models like _driver_, _car_, _route_. Application models enable you to represent these different entities in your code by creating respective _data structures_. When modeling data, you typically ask questions like: - What are the main entities/concepts in my application? - How do they relate to each other? - What are their main characteristics/properties? - How can they be represented with my technology stack? ## Data modeling without Prisma ORM Data modeling typically needs to happen on (at least) two levels: - On the **database** level - On the **application** level (i.e., in your programming language) The way that the application models are represented on both levels might differ due to a few reasons: - Databases and programming languages use different data types - Relations are represented differently in a database than in a programming language - Databases typically have more powerful data modeling capabilities, like indexes, cascading deletes, or a variety of additional constraints (e.g. unique, not null, ...) - Databases and programming languages have different technical constraints ### Data modeling on the database level #### Relational databases In relational databases, models are represented by _tables_. For example, you might define a `users` table to store information about the users of your application. Using PostgreSQL, you'd define it as follows: ```sql CREATE TABLE users ( user_id SERIAL PRIMARY KEY NOT NULL, name VARCHAR(255), email VARCHAR(255) UNIQUE NOT NULL, isAdmin BOOLEAN NOT NULL DEFAULT false ); ``` A visual representation of the `users` table with some random data might look as follows: | `user_id` | `name` | `email` | `isAdmin` | | :-------- | :------ | :---------------- | :-------- | | `1` | `Alice` | `alice@prisma.io` | `false` | | `2` | `Bob` | `bob@prisma.io` | `false` | | `3` | `Sarah` | `sarah@prisma.io` | `true` | It has the following columns: - `user_id`: An integer that increments with every new record in the `users` table. It also represents the [primary key](https://en.wikipedia.org/wiki/Primary_key) for each record. - `name`: A string with at most 255 characters. - `email`: A string with at most 255 characters. Additionally, the added constraints express that no two records can have duplicate values for the `email` column, and that _every_ record needs to have a value for it. - `isAdmin`: A boolean that indicates whether the user has admin rights (default value: `false`) #### MongoDB In MongoDB databases, models are represented by _collections_ and contain _documents_ that can have any structure: ```js { _id: '607ee94800bbe41f001fd568', slug: 'prisma-loves-mongodb', title: 'Prisma <3 MongoDB', body: "This is my first post. Isn't MongoDB + Prisma awesome?!" } ``` Prisma Client currently expects a consistent model and [normalized model design](https://www.mongodb.com/docs/manual/data-modeling/concepts/embedding-vs-references/#references). This means that: - If a model or field is not present in the Prisma schema, it is ignored - If a field is mandatory but not present in the MongoDB dataset, you will get an error ### Data modeling on the application level In addition to creating the tables that represent the entities from your application domain, you also need to create application models in your programming language. In object-oriented languages, this is often done by creating _classes_ to represent your models. Depending on the programming language, this might also be done with _interfaces_ or _structs_. There often is a strong correlation between the tables in your database and the models you define in your code. For example, to represent records from the aforementioned `users` table in your application, you might define a JavaScript (ES6) class looking similar to this: ```js class User { constructor(user_id, name, email, isAdmin) { this.user_id = user_id this.name = name this.email = email this.isAdmin = isAdmin } } ``` When using TypeScript, you might define an interface instead: ```js interface User { user_id: number name: string email: string isAdmin: boolean } ``` Notice how the `User` model in both cases has the same properties as the `users` table in the previous example. While it's often the case that there's a 1:1 mapping between database tables and application models, it can also happen that models are represented completely differently in the database and your application. With this setup, you can retrieve records from the `users` table and store them as instances of your `User` type. The following example code snippet uses [`pg`](https://node-postgres.com/) as the driver for PostgreSQL and creates a `User` instance based on the above defined JavaScript class: ```js const resultRows = await client.query('SELECT * FROM users WHERE user_id = 1') const userData = resultRows[0] const user = new User( userData.user_id, userData.name, userData.email, userData.isAdmin ) // user = { // user_id: 1, // name: "Alice", // email: "alice@prisma.io", // isAdmin: false // } ``` Notice that in these examples, the application models are "dumb", meaning they don't implement any logic but their sole purpose is to carry data as _plain old JavaScript objects_. ### Data modeling with ORMs ORMs are commonly used in object-oriented languages to make it easier for developers to work with a database. The key characteristic of an ORM is that it lets you model your application data in terms of _classes_ which are mapped to _tables_ in the underlying database. The main difference compared to the approaches explained above is these classes not only carry data but also implement a substantial amount of logic. Mostly for storage, retrieval, serialization, and deserialization, but sometimes they also implement business logic that's specific to your application. This means, you don't write SQL statements to read and write data in the database, but instead the instances of your model classes provide an API to store and retrieve data. [Sequelize](https://sequelize.org/) is a popular ORM in the Node.js ecosystem, this is how you'd define the same `User` model from the sections before using Sequelize's modeling approach: ```js class User extends Model {} User.init( { user_id: { type: Sequelize.INTEGER, primaryKey: true, autoIncrement: true, }, name: Sequelize.STRING(255), email: { type: Sequelize.STRING(255), unique: true, }, isAdmin: Sequelize.BOOLEAN, }, { sequelize, modelName: 'user' } ) ``` To get an example with this `User` class to work, you still need to create the corresponding table in the database. With Sequelize, you have two ways of doing this: - Run `User.sync()` (typically not recommended for production) - Use [Sequelize migrations](https://sequelize.org/v5/manual/migrations.html) to change your database schema Note that you'll never instantiate the `User` class manually (using `new User(...)`) as was shown in the previous section, but rather call _static_ methods on the `User` class which then return the `User` model instances: ```js const user = await User.findByPk(42) ``` The call to `findByPk` creates a SQL statement to retrieve the `User` record that's identified by the ID value `42`. The resulting `user` object is an instance of Sequelize's `Model` class (because `User` inherits from `Model`). It's not a POJO, but an object that implements additional behavior from Sequelize. ## Data modeling with Prisma ORM Depending on which parts of Prisma ORM you want to use in your application, the data modeling flow looks slightly different. The following two sections explain the workflows for using [**only Prisma Client**](#using-only-prisma-client) and using [**Prisma Client and Prisma Migrate**](#using-prisma-client-and-prisma-migrate). No matter which approach though, with Prisma ORM you never create application models in your programming language by manually defining classes, interfaces, or structs. Instead, the application models are defined in your [Prisma schema](/orm/prisma-schema): - **Only Prisma Client**: Application models in the Prisma schema are _generated based on the introspection of your database schema_. Data modeling happens primarily on the database-level. - **Prisma Client and Prisma Migrate**: Data modeling happens in the Prisma schema by _manually adding application models_ to it. Prisma Migrate maps these application models to tables in the underlying database (currently only supported for relational databases). As an example, the `User` model from the previous example would be represented as follows in the Prisma schema: ```prisma model User { user_id Int @id @default(autoincrement()) name String? email String @unique isAdmin Boolean @default(false) } ``` Once the application models are in your Prisma schema (whether they were added through introspection or manually by you), the next step typically is to generate Prisma Client which provides a programmatic and type-safe API to read and write data in the shape of your application models. Prisma Client uses TypeScript [type aliases](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases) to represent your application models in your code. For example, the `User` model would be represented as follows in the generated Prisma Client library: ```ts export type User = { id: number name: string | null email: string isAdmin: boolean } ``` In addition to the generated types, Prisma Client also provides a data access API that you can use once you've installed the `@prisma/client` package: ```js import { PrismaClient } from '@prisma/client' // or // const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() // use inside an `async` function to `await` the result await prisma.user.findUnique(...) await prisma.user.findMany(...) await prisma.user.create(...) await prisma.user.update(...) await prisma.user.delete(...) await prisma.user.upsert(...) ``` ### Using only Prisma Client When using only Prisma Client and _not_ using Prisma Migrate in your application, data modeling needs to happen on the database level via SQL. Once your SQL schema is ready, you use Prisma's introspection feature to add the application models to your Prisma schema. Finally, you generate Prisma Client which creates the types as well as the programmatic API for you to read and write data in your database. Here is an overview of the main workflow: 1. Change your database schema using SQL (e.g. `CREATE TABLE`, `ALTER TABLE`, ...) 1. Run `prisma db pull` to introspect the database and add application models to the Prisma schema 1. Run `prisma generate` to update your Prisma Client API ### Using Prisma Client and Prisma Migrate When using [Prisma Migrate](/orm/prisma-migrate), you define your application model in the Prisma schema and with relational databases use the `prisma migrate` subcommand to generate plain SQL migration files, which you can edit before applying. With MongoDB, you use `prisma db push` instead which applies the changes to your database directly. Here is an overview of the main workflow: 1. Manually change your application models in the Prisma schema (e.g. add a new model, remove an existing one, ...) 1. Run `prisma migrate dev` to create and apply a migration or run `prisma db push` to apply the changes directly (in both cases Prisma Client is automatically generated) --- # Introduction URL: https://www.prisma.io/docs/orm/overview/introduction/index This page gives a high-level overview of what Prisma ORM is and how it works. If you want to get started with a _practical introduction_ and learn about the Prisma Client API, head over to the [**Getting Started**](/getting-started) documentation. To learn more about the _motivation_ for Prisma ORM, check out the [**Why Prisma ORM?**](/orm/overview/introduction/why-prisma) page. ## In this section --- # REST URL: https://www.prisma.io/docs/orm/overview/prisma-in-your-stack/rest When building REST APIs, Prisma Client can be used inside your _route controllers_ to send databases queries. ![REST APIs with Prisma Client](../100-introduction/prisma-rest-apis.png) ## Supported libraries As Prisma Client is "only" responsible for sending queries to your database, it can be combined with any HTTP server library or web framework of your choice. Here's a non-exhaustive list of libraries and frameworks you can use with Prisma ORM: - [Express](https://expressjs.com/) - [koa](https://koajs.com/) - [hapi](https://hapi.dev/) - [Fastify](https://fastify.dev/) - [Sails](https://sailsjs.com/) - [AdonisJs](https://adonisjs.com/) - [NestJS](https://nestjs.com/) - [Next.js](https://nextjs.org/) - [Foal TS](https://foalts.org/) - [Polka](https://github.com/lukeed/polka) - [Micro](https://github.com/zeit/micro) - [Feathers](https://feathersjs.com/) - [Remix](https://remix.run/) ## REST API server example Assume you have a Prisma schema that looks similar to this: ```prisma datasource db { provider = "sqlite" url = "file:./dev.db" } generator client { provider = "prisma-client-js" } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User? @relation(fields: [authorId], references: [id]) authorId Int? } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } ``` You can now implement route controller (e.g. using Express) that use the generated [Prisma Client API](/orm/prisma-client) to perform a database operation when an incoming HTTP request arrives. This page only shows few sample code snippets; if you want to run these code snippets, you can use a [REST API example](https://pris.ly/e/ts/rest-express). #### `GET` ```ts app.get('/feed', async (req, res) => { const posts = await prisma.post.findMany({ where: { published: true }, include: { author: true }, }) res.json(posts) }) ``` Note that the `feed` endpoint in this case returns a nested JSON response of `Post` objects that _include_ an `author` object. Here's a sample response: ```json [ { "id": "21", "title": "Hello World", "content": "null", "published": "true", "authorId": 42, "author": { "id": "42", "name": "Alice", "email": "alice@prisma.io" } } ] ``` #### `POST` ```ts app.post(`/post`, async (req, res) => { const { title, content, authorEmail } = req.body const result = await prisma.post.create({ data: { title, content, published: false, author: { connect: { email: authorEmail } }, }, }) res.json(result) }) ``` #### `PUT` ```ts app.put('/publish/:id', async (req, res) => { const { id } = req.params const post = await prisma.post.update({ where: { id: Number(id) }, data: { published: true }, }) res.json(post) }) ``` #### `DELETE` ```ts app.delete(`/post/:id`, async (req, res) => { const { id } = req.params const post = await prisma.post.delete({ where: { id: Number(id), }, }) res.json(post) }) ``` ## Ready-to-run example projects You can find several ready-to-run examples that show how to implement a REST API with Prisma Client, as well as build full applications, in the [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository. | **Example** | **Stack** | **Description** | | ----------------------------------------------------------------------------------------------------------------------------- | ------------ | ---------------------------------------------- | | [`express`](https://pris.ly/e/ts/rest-express) | Backend only | REST API with Express for TypeScript | | [`fastify`](https://pris.ly/e/ts/rest-fastify) | Backend only | REST API using Fastify and Prisma Client. | | [`hapi`](https://pris.ly/e/ts/rest-hapi) | Backend only | REST API using hapi and Prisma Client | | [`nestjs`](https://pris.ly/e/ts/rest-nestjs) | Backend only | Nest.js app (Express) with a REST API | | [`nextjs`](https://pris.ly/e/orm/nextjs) | Fullstack | Next.js app (React) with a REST API | --- # GraphQL URL: https://www.prisma.io/docs/orm/overview/prisma-in-your-stack/graphql [GraphQL](https://graphql.org/) is a query language for APIs. It is often used as an alternative to RESTful APIs, but can also be used as an additional "gateway" layer on top of existing RESTful services. With Prisma ORM, you can build GraphQL servers that connect to a database. Prisma ORM is completely agnostic to the GraphQL tools you use. When building a GraphQL server, you can combine Prisma ORM with tools like Apollo Server, GraphQL Yoga, TypeGraphQL, GraphQL.js, or pretty much any tool or library that you're using in your GraphQL server setup. ## GraphQL servers under the hood A GraphQL server consists of two major components: - GraphQL schema (type definitions + resolvers) - HTTP server Note that a GraphQL schema can be written code-first or SDL-first. Check out this [article](https://www.prisma.io/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3) to learn more about these two approaches. If you like the SDL-first approach but still want to make your code type-safe, check out [GraphQL Code Generator](https://the-guild.dev/graphql/codegen) to generate various type definitions based on SDL. The GraphQL schema and HTTP server are typically handled by separate libraries. Here is an overview of current GraphQL server tools and their purpose: | Library (npm package) | Purpose | Compatible with Prisma ORM | Prisma integration | | :-------------------- | :-------------------------- | :------------------------- | :----------------------------------------------------------------------------- | | `graphql` | GraphQL schema (code-first) | Yes | No | | `graphql-tools` | GraphQL schema (SDL-first) | Yes | No | | `type-graphql` | GraphQL schema (code-first) | Yes | [`typegraphql-prisma`](https://www.npmjs.com/package/typegraphql-prisma) | | `nexus` | GraphQL schema (code-first) | Yes | [`nexus-prisma`](https://graphql-nexus.github.io/nexus-prisma/) _Early Preview_ | | `apollo-server` | HTTP server | Yes | n/a | | `express-graphql` | HTTP server | Yes | n/a | | `fastify-gql` | HTTP server | Yes | n/a | | `graphql-yoga` | HTTP server | Yes | n/a | In addition to these standalone and single-purpose libraries, there are several projects building integrated _application frameworks_: | Framework | Stack | Built by | Prisma ORM | Description | | :---------------------------------- | :-------- | :------------------------------------------------ | :------------------------- | :------------------------------------- | | [Redwood.js](https://rwsdk.com/) | Fullstack | [Tom Preston-Werner](https://github.com/mojombo/) | Built on top of Prisma ORM | _Bringing full-stack to the JAMstack._ | > **Note**: If you notice any GraphQL libraries/frameworks missing from the list, please let us know. ## Prisma ORM & GraphQL examples In the following section will find several ready-to-run examples that showcase how to use Prisma ORM with different combinations of the tools mentioned in the table above. | Example | HTTP Server | GraphQL schema | Description | | :------------------------------------------------------------------------------------------------------------------------------- | :---------------------- | :-------------- | :--------------------------------------------------------------------------------------------- | | [GraphQL API (Pothos)](https://pris.ly/e/ts/graphql) | `graphql-yoga` | `pothos` | GraphQL server based on [`graphql-yoga`](https://the-guild.dev/graphql/yoga-server) | | [GraphQL API (SDL-first)](https://pris.ly/e/ts/graphql-sdl-first) | `graphql-yoga` | n/a | GraphQL server based on the SDL-first approach | | [GraphQL API -- NestJs](https://pris.ly/e/ts/graphql-nestjs) | `@nestjs/apollo` | n/a | GraphQL server based on [NestJS](https://nestjs.com/) | | [GraphQL API -- NestJs (SDL-first)](https://pris.ly/e/ts/graphql-nestjs-sdl-first) | `@nestjs/apollo` | n/a | GraphQL server based on [NestJS](https://nestjs.com/) | | [GraphQL API (Nexus)](https://pris.ly/e/ts/graphql-nexus) | `@apollo/server` | `nexus` | GraphQL server based on [`@apollo/server`](https://www.apollographql.com/docs/apollo-server) | | [GraphQL API (TypeGraphQL)](https://pris.ly/e/ts/graphql-typegraphql) | `apollo-server` | `type-graphql` | GraphQL server based on the code-first approach of [TypeGraphQL](https://typegraphql.com/) | | [GraphQL API (Auth)](https://pris.ly/e/ts/graphql-auth) | `apollo-server` | `nexus` | GraphQL server with email-password authentication & permissions | | [Fullstack app](https://pris.ly/e/ts/graphql-nextjs) | `graphql-yoga` | `pothos` | Fullstack app with Next.js (React), Apollo Client, GraphQL Yoga and Pothos | | [GraphQL subscriptions](https://pris.ly/e/ts/graphql-subscriptions) | `apollo-server` | `nexus` | GraphQL server implementing realtime GraphQL subscriptions | | [GraphQL API -- Hapi](https://pris.ly/e/ts/graphql-hapi) | `apollo-server-hapi` | `nexus` | GraphQL server based on [Hapi](https://hapi.dev/) | | [GraphQL API -- Hapi (SDL-first)](https://pris.ly/e/ts/graphql-hapi-sdl-first) | `apollo-server-hapi` | `graphql-tools` | GraphQL server based on [Hapi](https://hapi.dev/) | | [GraphQL API -- Fastify](https://pris.ly/e/ts/graphql-fastify) | `fastify` & `mercurius` | n/a | GraphQL server based on [Fastify](https://fastify.dev/) and [Mercurius](https://mercurius.dev/) | | [GraphQL API -- Fastify (SDL-first)](https://pris.ly/e/ts/graphql-fastify-sdl-first) | `fastify` | `Nexus` | GraphQL server based on [Fastify](https://fastify.dev/) and [Mercurius](https://mercurius.dev/) | ## FAQ ### What is Prisma ORM's role in a GraphQL server? No matter which of the above GraphQL tools/libraries you use, Prisma ORM is used inside your GraphQL resolvers to connect to your database. It has the same role that any other ORM or SQL query builder would have inside your resolvers. In the resolver of a GraphQL query, Prisma ORM typically reads data from the database to return it in the GraphQL response. In the resolver of a GraphQL mutation, Prisma ORM typically also writes data to the database (e.g. creating new or updating existing records). ## Other GraphQL Resources Prisma curates [GraphQL Weekly](https://www.graphqlweekly.com/), a newsletter highlighting resources and updates from the GraphQL community. Subscribe to keep up-to-date with GraphQL articles, videos, tutorials, libraries, and more. --- # Fullstack URL: https://www.prisma.io/docs/orm/overview/prisma-in-your-stack/fullstack Fullstack frameworks, such as Next.js, Remix or SvelteKit, blur the lines between the server and the client. These frameworks also provide different patterns for fetching and mutating data on the server. You can query your database using Prisma Client, using your framework of choice, from the server-side part of your application. ## Supported frameworks Here's a non-exhaustive list of frameworks and libraries you can use with Prisma ORM: - [Next.js](https://nextjs.org/) - [Remix](https://remix.run) - [SvelteKit](https://svelte.dev/) - [Nuxt](https://nuxt.com/) - [Redwood](https://rwsdk.com/) - [t3 stack — using tRPC](https://create.t3.gg/) - [Wasp](https://wasp-lang.dev/) ## Fullstack app example (e.g. Next.js) :::tip If you want to learn how to build an app with Next.js and Prisma ORM, check out this comprehensive [video tutorial](https://www.youtube.com/watch?v=QXxy8Uv1LnQ&ab_channel=ByteGrad). ::: Assume you have a Prisma schema that looks similar to this: ```prisma datasource db { provider = "sqlite" url = "file:./dev.db" } generator client { provider = "prisma-client-js" } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User? @relation(fields: [authorId], references: [id]) authorId Int? } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } ``` You can now implement the logic for querying your database using [Prisma Client API](/orm/prisma-client) inside `getServerSideProps`, `getStaticProps`, API routes, or using API libraries such as [tRPC](https://trpc.io/) and [GraphQL](https://graphql.org/). ### `getServerSideProps` ```ts // (in /pages/index.tsx) // Alternatively, you can use `getStaticProps` // in place of `getServerSideProps`. export const getServerSideProps = async () => { const feed = await prisma.post.findMany({ where: { published: true, }, }) return { props: { feed } } } ``` Next.js will pass the props to your React component where you can display the data from your database. ### API Routes ```ts // Fetch all posts (in /pages/api/posts.ts) const prisma = new PrismaClient() export default async function handle(req, res) { const posts = await prisma.post.findMany({ where: { published: true, }, }) res.json(posts) } ``` Note that you can use Prisma ORM inside of Next.js API routes to send queries to your database – with REST, GraphQL, and tRPC. You can then fetch data and display it in your frontend. ## Ready-to-run fullstack example projects You can find several ready-to-run examples that show how to fullstack apps with Prisma Client in the [`prisma-examples`](https://github.com/prisma/prisma-examples/) repository. | **Example** | **Description** | | :----------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------- | | [Next.js](https://pris.ly/e/orm/nextjs) | Fullstack Next.js 15 app | | [Next.js (GraphQL)](https://pris.ly/e/ts/graphql-nextjs) | Fullstack Next.js app using GraphQL Yoga, Pothos, & Apollo Client | | [Remix](https://pris.ly/e/ts/remix) | Fullstack Remix app using actions and loaders | | [SvelteKit](https://pris.ly/e/ts/sveltekit) | Fullstack Sveltekit app using actions and loaders | | [Nuxt](https://pris.ly/e/ts/rest-nuxtjs) | Fullstack Nuxt app using API routes | --- # Is Prisma ORM an ORM? URL: https://www.prisma.io/docs/orm/overview/prisma-in-your-stack/is-prisma-an-orm To answer the question briefly: _Yes, Prisma ORM is a new kind of ORM that fundamentally differs from traditional ORMs and doesn't suffer from many of the problems commonly associated with these_. Traditional ORMs provide an object-oriented way for working with relational databases by mapping tables to _model classes_ in your programming language. This approach leads to many problems that are caused by the [object-relational impedance mismatch](https://en.wikipedia.org/wiki/Object%E2%80%93relational_impedance_mismatch). Prisma ORM works fundamentally different compared to that. With Prisma ORM, you define your models in the declarative [Prisma schema](/orm/prisma-schema) which serves as the single source of truth for your database schema and the models in your programming language. In your application code, you can then use Prisma Client to read and write data in your database in a type-safe manner without the overhead of managing complex model instances. This makes the process of querying data a lot more natural as well as more predictable since Prisma Client always returns plain JavaScript objects. In this article, you will learn in more detail about ORM patterns and workflows, how Prisma ORM implements the Data Mapper pattern, and the benefits of Prisma ORM's approach. ## What are ORMs? If you're already familiar with ORMs, feel free to jump to the [next section](#prisma-orm) on Prisma ORM. ### ORM Patterns - Active Record and Data Mapper ORMs provide a high-level database abstraction. They expose a programmatic interface through objects to create, read, delete, and manipulate data while hiding some of the complexity of the database. The idea with ORMs is that you define your models as **classes** that map to tables in a database. The classes and their instances provide you with a programmatic API to read and write data in the database. There are two common ORM patterns: [_Active Record_](https://en.wikipedia.org/wiki/Active_record_pattern) and [_Data Mapper_](https://en.wikipedia.org/wiki/Data_mapper_pattern) which differ in how they transfer data between objects and the database. While both patterns require you to define classes as the main building block, the most notable difference between the two is that the Data Mapper pattern decouples in-memory objects in the application code from the database and uses the data mapper layer to transfer data between the two. In practice, this means that with Data Mapper the in-memory objects (representing data in the database) don't even know that there’s a database present. #### Active Record _Active Record_ ORMs map model classes to database tables where the structure of the two representations is closely related, e.g. each field in the model class will have a matching column in the database table. Instances of the model classes wrap database rows and carry both the data and the access logic to handle persisting changes in the database. Additionally, model classes can carry business logic specific to the data in the model. The model class typically has methods that do the following: - Construct an instance of the model from an SQL query. - Construct a new instance for later insertion into the table. - Wrap commonly used SQL queries and return Active Record objects. - Update the database and insert into it the data in the Active Record. - Get and set the fields. - Implement business logic. #### Data Mapper _Data Mapper_ ORMs, in contrast to Active Record, decouple the application's in-memory representation of data from the database's representation. The decoupling is achieved by requiring you to separate the mapping responsibility into two types of classes: - **Entity classes**: The application's in-memory representation of entities which have no knowledge of the database - **Mapper classes**: These have two responsibilities: - Transforming the data between the two representations. - Generating the SQL necessary to fetch data from the database and persist changes in the database. Data Mapper ORMs allow for greater flexibility between the problem domain as implemented in code and the database. This is because the data mapper pattern allows you to hide the ways in which your database is implemented which isn’t an ideal way to think about your domain behind the whole data-mapping layer. One of the reasons that traditional data mapper ORMs do this is due to the structure of organizations where the two responsibilities would be handled by separate teams, e.g., [DBAs](https://en.wikipedia.org/wiki/Database_administrator) and backend developers. In reality, not all Data Mapper ORMs adhere to this pattern strictly. For example, [TypeORM](https://github.com/typeorm/typeorm/blob/master/docs/active-record-data-mapper.md#what-is-the-data-mapper-pattern), a popular ORM in the TypeScript ecosystem which supports both Active Record and Data Mapper, takes the following approach to Data Mapper: - Entity classes use decorators (`@Column`) to map class properties to table columns and are aware of the database. - Instead of mapper classes, _repository_ classes are used for querying the database and may contain custom queries. Repositories use the decorators to determine the mapping between entity properties and database columns. Given the following `User` table in the database: ![user-table](../100-introduction/user-table.png) This is what the corresponding entity class would look like: ```ts import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm' @Entity() export class User { @PrimaryGeneratedColumn() id: number @Column({ name: 'first_name' }) firstName: string @Column({ name: 'last_name' }) lastName: string @Column({ unique: true }) email: string } ``` ### Schema migration workflows A central part of developing applications that make use of a database is changing the database schema to accommodate new features and to better fit the problem you're solving. In this section, we'll discuss what [schema migrations](https://www.prisma.io/dataguide/types/relational/what-are-database-migrations) are and how they affect the workflow. Because the ORM sits between the developer and the database, most ORMs provide a **migration tool** to assist with the creation and modification of the database schema. A migration is a set of steps to take the database schema from one state to another. The first migration usually creates tables and indices. Subsequent migrations may add or remove columns, introduce new indices, or create new tables. Depending on the migration tool, the migration may be in the form of SQL statements or programmatic code which will get converted to SQL statements (as with [ActiveRecord](https://guides.rubyonrails.org/active_record_migrations.html) and [SQLAlchemy](https://alembic.sqlalchemy.org/en/latest/tutorial.html#create-a-migration-script)). Because databases usually contain data, migrations assist you with breaking down schema changes into smaller units which helps avoid inadvertent data loss. Assuming you were starting a project from scratch, this is what a full workflow would look like: you create a migration that will create the `User` table in the database schema and define the `User` entity class as in the example above. Then, as the project progresses and you decide you want to add a new `salutation` column to the `User` table, you would create another migration which would alter the table and add the `salutation` column. Let's take a look at how that would look like with a TypeORM migration: ```ts import { MigrationInterface, QueryRunner } from 'typeorm' export class UserRefactoring1604448000 implements MigrationInterface { async up(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "User" ADD COLUMN "salutation" TEXT`) } async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE "User" DROP COLUMN "salutation"`) } } ``` Once a migration is carried out and the database schema has been altered, the entity and mapper classes must also be updated to account for the new `salutation` column. With TypeORM that means adding a `salutation` property to the `User` entity class: ```ts highlight=17,18;normal import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm' @Entity() export class User { @PrimaryGeneratedColumn() id: number @Column({ name: 'first_name' }) firstName: string @Column({ name: 'last_name' }) lastName: string @Column({ unique: true }) email: string //highlight-start @Column() salutation: string //highlight-end } ``` Synchronizing such changes can be a challenge with ORMs because the changes are applied manually and are not easily verifiable programmatically. Renaming an existing column can be even more cumbersome and involve searching and replacing references to the column. > **Note:** Django's [makemigrations](https://docs.djangoproject.com/en/3.1/ref/django-admin/#django-admin-makemigrations) CLI generates migrations by inspecting changes in models which, similar to Prisma ORM, does away with the synchronization problem. In summary, evolving the schema is a key part of building applications. With ORMs, the workflow for updating the schema involves using a migration tool to create a migration followed by updating the corresponding entity and mapper classes (depending on the implementation). As you'll see, Prisma ORM takes a different approach to this. Now that you've seen what migrations are and how they fit into the development workflows, you will learn more about the benefits and drawbacks of ORMs. ### Benefits of ORMs There are different reasons why developers choose to use ORMs: - ORMs facilitate implementing the domain model. The domain model is an object model that incorporates the behavior and data of your business logic. In other words, it allows you to focus on real business concepts rather than the database structure or SQL semantics. - ORMs help reduce the amount of code. They save you from writing repetitive SQL statements for common CRUD (Create Read Update Delete) operations and escaping user input to prevent vulnerabilities such as SQL injections. - ORMs require you to write little to no SQL (depending on your complexity you may still need to write the odd raw query). This is beneficial for developers who are not familiar with SQL but still want to work with a database. - Many ORMs abstract database-specific details. In theory, this means that an ORM can make changing from one database to another easier. It should be noted that in practice applications rarely change the database they use. As with all abstractions that aim to improve productivity, there are also drawbacks to using ORMs. ### Drawbacks of ORMs The drawbacks of ORMs are not always apparent when you start using them. This section covers some of the commonly accepted ones: - With ORMs, you form an object graph representation of database tables which may lead to the [object-relational impedance mismatch](https://en.wikipedia.org/wiki/Object-relational_impedance_mismatch). This happens when the problem you are solving forms a complex object graph which doesn't trivially map to a relational database. Synchronizing between two different representations of data, one in the relational database, and the other in-memory (with objects) is quite difficult. This is because objects are more flexible and varied in the way they can relate to each other compared to relational database records. - While ORMs handle the complexity associated with the problem, the synchronization problem doesn't go away. Any changes to the database schema or the data model require the changes to be mapped back to the other side. This burden is often on the developer. In the context of a team working on a project, database schema changes require coordination. - ORMs tend to have a large API surface due to the complexity they encapsulate. The flip side of not having to write SQL is that you spend a lot of time learning how to use the ORM. This applies to most abstractions, however without understanding how the database works, improving slow queries can be difficult. - Some _complex queries_ aren't supported by ORMs due to the flexibility that SQL offers. This problem is alleviated by raw SQL querying functionality in which you pass the ORM a SQL statement string and the query is run for you. Now that the costs and benefits of ORMs have been covered, you can better understand what Prisma ORM is and how it fits in. ## Prisma ORM Prisma ORM is a **next-generation ORM** that makes working with databases easy for application developers and features the following tools: - [**Prisma Client**](/orm/prisma-client): Auto-generated and type-safe database client for use in your application. - [**Prisma Migrate**](/orm/prisma-migrate): A declarative data modeling and migration tool. - [**Prisma Studio**](/orm/tools/prisma-studio): A modern GUI for browsing and managing data in your database. > **Note:** Since Prisma Client is the most prominent tool, we often refer to it as simply Prisma. These three tools use the [Prisma schema](/orm/prisma-schema) as a single source of truth for the database schema, your application's object schema, and the mapping between the two. It's defined by you and is your main way of configuring Prisma ORM. Prisma ORM makes you productive and confident in the software you're building with features such as _type safety_, rich auto-completion, and a natural API for fetching relations. In the next section, you will learn about how Prisma ORM implements the Data Mapper ORM pattern. ### How Prisma ORM implements the Data Mapper pattern As mentioned earlier in the article, the Data Mapper pattern aligns well with organizations where the database and application are owned by different teams. With the rise of modern cloud environments with managed database services and DevOps practices, more teams embrace a cross-functional approach, whereby teams own both the full development cycle including the database and operational concerns. Prisma ORM enables the evolution of the DB schema and object schema in tandem, thereby reducing the need for deviation in the first place, while still allowing you to keep your application and database somewhat decoupled using `@map` attributes. While this may seem like a limitation, it prevents the domain model's evolution (through the object schema) from getting imposed on the database as an afterthought. To understand how Prisma ORM's implementation of the Data Mapper pattern differs conceptually to traditional Data Mapper ORMs, here's a brief comparison of their concepts and building blocks: | Concept | Description | Building block in traditional ORMs | Building block in Prisma ORM | Source of truth in Prisma ORM | | --------------- | -------------------------------------------------------------------- | ---------------------------------------------- | ------------------------------------ | ------------------------------------ | | Object schema | The in-memory data structures in your applications | Model classes | Generated TypeScript types | Models in the Prisma schema | | Data Mapper | The code which transforms between the object schema and the database | Mapper classes | Generated functions in Prisma Client | @map attributes in the Prisma schema | | Database schema | The structure of data in the database, e.g., tables and columns | SQL written by hand or with a programmatic API | SQL generated by Prisma Migrate | Prisma schema | Prisma ORM aligns with the Data Mapper pattern with the following added benefits: - Reducing the boilerplate of defining classes and mapping logic by generating a Prisma Client based on the Prisma schema. - Eliminating the synchronization challenges between application objects and the database schema. - Database migrations are a first-class citizen as they're derived from the Prisma schema. Now that we've talked about the concepts behind Prisma ORM's approach to Data Mapper, we can go through how the Prisma schema works in practice. ### Prisma schema At the heart of Prisma's implementation of the Data Mapper pattern is the _Prisma schema_ – a single source of truth for the following responsibilities: - Configuring how Prisma connects to your database. - Generating Prisma Client – the type-safe ORM for use in your application code. - Creating and evolving the database schema with Prisma Migrate. - Defining the mapping between application objects and database columns. Models in Prisma ORM mean something slightly different to Active Record ORMs. With Prisma ORM, models are defined in the Prisma schema as abstract entities which describe tables, relations, and the mappings between columns to properties in Prisma Client. As an example, here's a Prisma schema for a blog: ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Post { id Int @id @default(autoincrement()) title String content String? @map("post_content") published Boolean @default(false) author User? @relation(fields: [authorId], references: [id]) authorId Int? } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } ``` Here's a break down of the example above: - The `datasource` block defines the connection to the database. - The `generator` block tells Prisma ORM to generate Prisma Client for TypeScript and Node.js. - The `Post` and `User` models map to database tables. - The two models have a _1-n_ relation where each `User` can have many related `Post`s. - Each field in the models has a type, e.g. the `id` has the type `Int`. - Fields may contain field attributes to define: - Primary keys with the `@id` attribute. - Unique keys with the `@unique` attribute. - Default values with the `@default` attribute. - Mapping between table columns and Prisma Client fields with the `@map` attribute, e.g., the `content` field (which will be accessible in Prisma Client) maps to the `post_content` database column. The `User` / `Post` relation can be visualized with the following diagram: ![1-n relation between User and Post](../100-introduction/user-post-relation-1-n.png) At a Prisma ORM level, the `User` / `Post` relation is made up of: - The scalar `authorId` field, which is referenced by the `@relation` attribute. This field exists in the database table – it is the foreign key that connects Post and User. - The two relation fields: `author` and `posts` **do not exist** in the database table. Relation fields define connections between models at the Prisma ORM level and exist only in the Prisma schema and generated Prisma Client, where they are used to access the relations. The declarative nature of Prisma schema is concise and allows defining the database schema and corresponding representation in Prisma Client. In the next section, you will learn about Prisma ORM's supported workflows. ### Prisma ORM workflow The workflow with Prisma ORM is slightly different to traditional ORMs. You can use Prisma ORM when building new applications from scratch or adopt it incrementally: - _New application_ (greenfield): Projects that have no database schema yet can use Prisma Migrate to create the database schema. - _Existing application_ (brownfield): Projects that already have a database schema can be [introspected](/orm/prisma-schema/introspection) by Prisma ORM to generate the Prisma schema and Prisma Client. This use-case works with any existing migration tool and is useful for incremental adoption. It's possible to switch to Prisma Migrate as the migration tool. However, this is optional. With both workflows, the Prisma schema is the main configuration file. #### Workflow for incremental adoption in projects with an existing database Brownfield projects typically already have some database abstraction and schema. Prisma ORM can integrate with such projects by introspecting the existing database to obtain a Prisma schema that reflects the existing database schema and to generate Prisma Client. This workflow is compatible with any migration tool and ORM which you may already be using. If you prefer to incrementally evaluate and adopt, this approach can be used as part of a [parallel adoption strategy](https://en.wikipedia.org/wiki/Parallel_adoption). A non-exhaustive list of setups compatible with this workflow: - Projects using plain SQL files with `CREATE TABLE` and `ALTER TABLE` to create and alter the database schema. - Projects using a third party migration library like [db-migrate](https://github.com/db-migrate/node-db-migrate) or [Umzug](https://github.com/sequelize/umzug). - Projects already using an ORM. In this case, database access through the ORM remains unchanged while the generated Prisma Client can be incrementally adopted. In practice, these are the steps necessary to introspect an existing DB and generate Prisma Client: 1. Create a `schema.prisma` defining the `datasource` (in this case, your existing DB) and `generator`: ```prisma datasource db { provider = "postgresql" url = "postgresql://janedoe:janedoe@localhost:5432/hello-prisma" } generator client { provider = "prisma-client-js" } ``` 2. Run `prisma db pull` to populate the Prisma schema with models derived from your database schema. 3. (Optional) Customize [field and model mappings](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections) between Prisma Client and the database. 4. Run `prisma generate`. Prisma ORM will generate Prisma Client inside the `node_modules` folder, from which it can be imported in your application. For more extensive usage documentation, see the [Prisma Client API](/orm/prisma-client) docs. To summarize, Prisma Client can be integrated into projects with an existing database and tooling as part of a parallel adoption strategy. New projects will use a different workflow detailed next. #### Workflow for new projects Prisma ORM is different from ORMs in terms of the workflows it supports. A closer look at the steps necessary to create and change a new database schema is useful for understanding Prisma Migrate. Prisma Migrate is a CLI for declarative data modeling & migrations. Unlike most migration tools that come as part of an ORM, you only need to describe the current schema, instead of the operations to move from one state to another. Prisma Migrate infers the operations, generates the SQL and carries out the migration for you. This example demonstrates using Prisma ORM in a new project with a new database schema similar to the blog example above: 1. Create the Prisma schema: ```prisma // schema.prisma datasource db { provider = "postgresql" url = "postgresql://janedoe:janedoe@localhost:5432/hello-prisma" } generator client { provider = "prisma-client-js" } model Post { id Int @id @default(autoincrement()) title String content String? @map("post_content") published Boolean @default(false) author User? @relation(fields: [authorId], references: [id]) authorId Int? } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } ``` 2. Run `prisma migrate` to generate the SQL for the migration, apply it to the database, and generate Prisma Client. For any further changes to the database schema: 1. Apply changes to the Prisma schema, e.g., add a `registrationDate` field to the `User` model 1. Run `prisma migrate` again. The last step demonstrates how declarative migrations work by adding a field to the Prisma schema and using Prisma Migrate to transform the database schema to the desired state. After the migration is run, Prisma Client is automatically regenerated so that it reflects the updated schema. If you don't want to use Prisma Migrate but still want to use the type-safe generated Prisma Client in a new project, see the next section. ##### Alternative for new projects without Prisma Migrate It is possible to use Prisma Client in a new project with a third-party migration tool instead of Prisma Migrate. For example, a new project could choose to use the Node.js migration framework [db-migrate](https://github.com/db-migrate/node-db-migrate) to create the database schema and migrations and Prisma Client for querying. In essence, this is covered by the [workflow for existing databases](#workflow-for-incremental-adoption-in-projects-with-an-existing-database). ## Accessing data with Prisma Client So far, the article covered the concepts behind Prisma ORM, its implementation of the Data Mapper pattern, and the workflows it supports. In this last section, you will see how to access data in your application using Prisma Client. Accessing the database with Prisma Client happens through the query methods it exposes. All queries return plain old JavaScript objects. Given the blog schema from above, fetching a user looks as follows: ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() const user = await prisma.user.findUnique({ where: { email: 'alice@prisma.io', }, }) ``` In this query, the `findUnique()` method is used to fetch a single row from the `User` table. By default, Prisma ORM will return all the scalar fields in the `User` table. > **Note:** The example uses TypeScript to make full use of the type safety features offered by Prisma Client. However, Prisma ORM also works with [JavaScript in Node.js](https://dev.to/prisma/productive-development-with-prisma-s-zero-cost-type-safety-4od2). Prisma Client maps queries and results to [structural types](https://en.wikipedia.org/wiki/Structural_type_system) by generating code from the Prisma schema. This means that `user` has an associated type in the generated Prisma Client: ``` export type User = { id: number email: string name: string | null } ``` This ensures that accessing a non-existent field will raise a type error. More broadly, it means that the result's type for every query is known ahead of running the query, which helps catch errors. For example, the following code snippet will raise a type error: ```ts console.log(user.lastName) // Property 'lastName' does not exist on type 'User'. ``` ### Fetching relations Fetch relations with Prisma Client is done with the `include` option. For example, to fetch a user and their posts would be done as follows: ```ts const user = await prisma.user.findUnique({ where: { email: 'alice@prisma.io', }, include: { posts: true, }, }) ``` With this query, `user`'s type will also include `Post`s which can be accessed with the `posts` array field: ```ts console.log(user.posts[0].title) ``` The example only scratches the surface of Prisma Client's API for [CRUD operations](/orm/prisma-client/queries/crud) which you can learn more about in the docs. The main idea is that all queries and results are backed by types and you have full control over how relations are fetched. ## Conclusion In summary, Prisma ORM is a new kind of Data Mapper ORM that differs from traditional ORMs and doesn't suffer from the problems commonly associated with them. Unlike traditional ORMs, with Prisma ORM, you define the Prisma schema – a declarative single source of truth for the database schema and application models. All queries in Prisma Client return plain JavaScript objects which makes the process of interacting with the database a lot more natural as well as more predictable. Prisma ORM supports two main workflows for starting new projects and adopting in an existing project. For both workflows, your main avenue for configuration is via the Prisma schema. Like all abstractions, both Prisma ORM and other ORMs hide away some of the underlying details of the database with different assumptions. These differences and your use case all affect the workflow and cost of adoption. Hopefully understanding how they differ can help you make an informed decision. --- # Prisma ORM in your stack URL: https://www.prisma.io/docs/orm/overview/prisma-in-your-stack/index Prisma ORM provides a fully type-safe API and simplified database access. You can use Prisma ORM tools to build a GraphQL or REST API, or as part of a fullstack application - the extent to which you incorporate Prisma ORM is up to you. ## In this section --- # Database drivers URL: https://www.prisma.io/docs/orm/overview/databases/database-drivers ## Default built-in drivers One of Prisma Client's components is the [Query Engine](/orm/more/under-the-hood/engines). The Query Engine is responsible for transforming Prisma Client queries into SQL statements. It connects to your database via TCP using built-in drivers that don't require additional setup. ![Query flow from the user application to the database with Prisma Client](./images/drivers/qe-query-execution-flow.png) ## Driver adapters Prisma Client can connect and run queries against your database using JavaScript database drivers using **driver adapters**. Adapters act as _translators_ between Prisma Client and the JavaScript database driver. Prisma Client will use the Query Engine to transform the Prisma Client query to SQL and run the generated SQL queries via the JavaScript database driver. ![Query flow from the user application to the database using Prisma Client and driver adapters](./images/drivers/qe-query-engine-adapter.png) There are two different types of driver adapters: - [Database driver adapters](#database-driver-adapters) - [Serverless driver adapters](#serverless-driver-adapters) > **Note**: Driver adapters enable [edge deployments](/orm/prisma-client/deployment/edge/overview) of applications that use Prisma ORM. ### Database driver adapters You can connect to your database using a Node.js-based driver from Prisma Client using a database driver adapter. Prisma maintains the following database driver adapters: - [PostgreSQL](/orm/overview/databases/postgresql#using-the-node-postgres-driver) - [Turso / LibSQL](/orm/overview/databases/turso#how-to-connect-and-query-a-turso-database) ### Serverless driver adapters Database providers, such as Neon and PlanetScale, allow you to connect to your database using other protocols besides TCP, such as HTTP and WebSockets. These database drivers are optimized for connecting to your database in serverless and edge environments. Prisma ORM maintains the following serverless driver adapters: - [Neon](/orm/overview/databases/neon#how-to-use-neons-serverless-driver-with-prisma-orm-preview) (and Vercel Postgres) - [PlanetScale](/orm/overview/databases/planetscale#how-to-use-the-planetscale-serverless-driver-with-prisma-orm-preview) - [Cloudflare D1](/orm/overview/databases/cloudflare-d1) ### Community-maintained database driver adapters You can also build your own driver adapter for the database you're using. The following is a list of community-maintained driver adapters: - [TiDB Cloud Serverless Driver](https://github.com/tidbcloud/prisma-adapter) - [PGlite - Postgres in WASM](https://github.com/lucasthevenet/pglite-utils/tree/main/packages/prisma-adapter) ## How to use driver adapters To use this feature: 1. Update the `previewFeatures` block in your schema to include the `driverAdapters` Preview feature: ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["driverAdapters"] } ``` 2. Generate Prisma Client: ```bash npx prisma generate ``` 3. Refer to the following pages to learn more about how to use the specific driver adapters with the specific database providers: - [PostgreSQL](/orm/overview/databases/postgresql#using-the-node-postgres-driver) - [Neon](/orm/overview/databases/neon#how-to-use-neons-serverless-driver-with-prisma-orm-preview) - [PlanetScale](/orm/overview/databases/planetscale#how-to-use-the-planetscale-serverless-driver-with-prisma-orm-preview) - [Turso](/orm/overview/databases/turso#how-to-connect-and-query-a-turso-database) - [Cloudflare D1](/orm/overview/databases/cloudflare-d1) ## Notes about using driver adapters ### New driver adapters API in v6.6.0 In [v6.6.0](https://github.com/prisma/prisma/releases/tag/6.6.0), we introduced a simplified version for instantiating Prisma Client when using driver adapters. You now don't need to create an instance of the driver/client to pass to a driver adapter, instead you can just create the driver adapter directly (and pass the driver's options to it if needed). Here is an example using the `@prisma/adapter-libsql` adapter: #### Before 6.6.0 Earlier versions of Prisma ORM required you to first instantiate the driver itself, and then use that instance to create the Prisma driver adapter. Here is an example using the `@libsql/client` driver for LibSQL: ```typescript import { createClient } from '@libsql/client' import { PrismaLibSQL } from '@prisma/adapter-libsql' import { PrismaClient } from '@prisma/client' // Old way of using driver adapters (before 6.6.0) const driver = createClient({ url: env.LIBSQL_DATABASE_URL, authToken: env.LIBSQL_DATABASE_TOKEN, }) const adapter = new PrismaLibSQL(driver) const prisma = new PrismaClient({ adapter }) ``` #### 6.6.0 and later As of the 6.6.0 release, you instantiate the driver adapter _directly_ with the options of your preferred JS-native driver.: ```typescript import { PrismaLibSQL } from '@prisma/adapter-libsql' import { PrismaClient } from '../prisma/prisma-client' const adapter = new PrismaLibSQL({ url: env.LIBSQL_DATABASE_URL, authToken: env.LIBSQL_DATABASE_TOKEN, }) const prisma = new PrismaClient({ adapter }) ``` ### Driver adapters don't read the connection string from the Prisma schema When using Prisma ORM's built-in drivers, the connection string is read from the `url` field of the `datasource` block in your Prisma schema. On the other hand, when using a driver adapter, the connection string needs to be provided in your _application code_ when the driver adapter is set up initially. Here is how this is done for the `pg` driver and the `@prisma/adapter-pg` adapter: ```ts import { PrismaClient } from '@prisma/client' import { PrismaPg } from '@prisma/adapter-pg' const adapter = new PrismaPg({ connectionString: env.DATABASE_URL }) const prisma = new PrismaClient({ adapter }) ``` See the docs for the driver adapter you're using for concrete setup instructions. ### Driver adapters and custom output paths Since Prisma 5.9.0, when using the driver adapters Preview feature along with a [custom output path for Prisma Client](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path), you cannot reference Prisma Client using a relative path. Let's assume you had `output` in your Prisma schema set to `../src/generated/client`: ```prisma generator client { provider = "prisma-client-js" output = "../src/generated/client" } ``` What you should _not_ do is reference that path relatively: ```ts no-copy // what not to do! import { PrismaClient } from './src/generated/client' const client = new PrismaClient() ``` Instead, you will need to use a linked dependency. ```terminal npm add db@./src/generated/client ``` ```terminal pnpm add db@link:./src/generated/client ``` ```terminal yarn add db@link:./src/generated/client ``` Now, you should be able to reference your generated client using `db`! ```ts import { PrismaClient } from 'db' const client = new PrismaClient() ``` ### Driver adapters and specific frameworks #### Nuxt Using a driver adapter with [Nuxt](https://nuxt.com/) to deploy to an edge function environment does not work out of the box, but adding the `nitro.experimental.wasm` configuration option fixes that: ```ts export default defineNuxtConfig({ // ... nitro: { // ... experimental: { wasm: true, }, }, // ... }) ``` --- # PostgreSQL URL: https://www.prisma.io/docs/orm/overview/databases/postgresql The PostgreSQL data source connector connects Prisma ORM to a [PostgreSQL](https://www.postgresql.org/) database server. By default, the PostgreSQL connector contains a database driver responsible for connecting to your database. You can use a [driver adapter](/orm/overview/databases/database-drivers#driver-adapters) (Preview) to connect to your database using a JavaScript database driver from Prisma Client. :::info Need a Postgres instance yesterday? With [Prisma Postgres](https://www.prisma.io/postgres?utm_source=docs&utm_campaign=postgresql) you can get a database running on bare-metal in three clicks. Connection pooling, query caching, and automated backups are all included. [Visit the Console](https://console.prisma.io?utm_source=docs&utm_campaign=postgresql) to get started today. Want any even faster way to get started with Prisma Postgres? Just run `npx prisma init --db` in your terminal. 🚀 ::: ## Example To connect to a PostgreSQL database server, you need to configure a [`datasource`](/orm/prisma-schema/overview/data-sources) block in your [Prisma schema](/orm/prisma-schema): ```prisma file=schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` The fields passed to the `datasource` block are: - `provider`: Specifies the `postgresql` data source connector. - `url`: Specifies the [connection URL](#connection-url) for the PostgreSQL database server. In this case, an [environment variable is used](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the connection URL. ## Using the `node-postgres` driver As of [`v5.4.0`](https://github.com/prisma/prisma/releases/tag/5.4.0), you can use Prisma ORM with database drivers from the JavaScript ecosystem (instead of using Prisma ORM's built-in drivers). You can do this by using a [driver adapter](/orm/overview/databases/database-drivers). For PostgreSQL, [`node-postgres`](https://node-postgres.com) (`pg`) is one of the most popular drivers in the JavaScript ecosystem. It can be used with any PostgreSQL database that's accessed via TCP. This section explains how you can use it with Prisma ORM and the `@prisma/adapter-pg` driver adapter. ### 1. Enable the `driverAdapters` Preview feature flag Since driver adapters are currently in [Preview](/orm/more/releases#preview), you need to enable its feature flag on the `datasource` block in your Prisma schema: ```prisma // schema.prisma generator client { provider = "prisma-client-js" previewFeatures = ["driverAdapters"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` Once you have added the feature flag to your schema, re-generate Prisma Client: ```terminal copy npx prisma generate ``` ### 2. Install the dependencies Next, install Prisma ORM's driver adapter for `pg`: ```terminal copy npm install @prisma/adapter-pg ``` ### 3. Instantiate Prisma Client using the driver adapter Finally, when you instantiate Prisma Client, you need to pass an instance of Prisma ORM's driver adapter to the `PrismaClient` constructor: ```ts copy import { PrismaPg } from '@prisma/adapter-pg' import { PrismaClient } from '@prisma/client' const connectionString = `${process.env.DATABASE_URL}` const adapter = new PrismaPg({ connectionString }); const prisma = new PrismaClient({ adapter }); ``` Notice that this code requires the `DATABASE_URL` environment variable to be set to your PostgreSQL connection string. You can learn more about the connection string below. ### Notes #### Specifying a PostgreSQL schema You can specify a [PostgreSQL schema](https://www.postgresql.org/docs/current/ddl-schemas.html) by passing in the `schema` option when instantiating `PrismaPg`: ```ts const adapter = new PrismaPg( { connectionString }, { schema: 'myPostgresSchema' } ) ``` ## Connection details ### Connection URL Prisma ORM follows the connection URL format specified by [PostgreSQL's official guidelines](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING), but does not support all arguments and includes additional arguments such as `schema`. Here's an overview of the components needed for a PostgreSQL connection URL: ![Structure of the PostgreSQL connection URL](./postgresql-connection-string.png) #### Base URL and path Here is an example of the structure of the _base URL_ and the _path_ using placeholder values in uppercase letters: ``` postgresql://USER:PASSWORD@HOST:PORT/DATABASE ``` The following components make up the _base URL_ of your database, they are always required: | Name | Placeholder | Description | | :------- | :---------- | :-------------------------------------------------------------------------------------------------------------- | | Host | `HOST` | IP address/domain of your database server, e.g. `localhost` | | Port | `PORT` | Port on which your database server is running, e.g. `5432` | | User | `USER` | Name of your database user, e.g. `janedoe` | | Password | `PASSWORD` | Password for your database user | | Database | `DATABASE` | Name of the [database](https://www.postgresql.org/docs/12/manage-ag-overview.html) you want to use, e.g. `mydb` | You must [percentage-encode special characters](/orm/reference/connection-urls#special-characters). #### Arguments A connection URL can also take arguments. Here is the same example from above with placeholder values in uppercase letters for three _arguments_: ``` postgresql://USER:PASSWORD@HOST:PORT/DATABASE?KEY1=VALUE&KEY2=VALUE&KEY3=VALUE ``` The following arguments can be used: | Argument name | Required | Default | Description | | :--------------------- | :------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `schema` | **Yes** | `public` | Name of the [schema](https://www.postgresql.org/docs/12/ddl-schemas.html) you want to use, e.g. `myschema` | | `connection_limit` | No | `num_cpus * 2 + 1` | Maximum size of the [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool) | | `connect_timeout` | No | `5` | Maximum number of seconds to wait for a new connection to be opened, `0` means no timeout | | `pool_timeout` | No | `10` | Maximum number of seconds to wait for a new connection from the pool, `0` means no timeout | | `sslmode` | No | `prefer` | Configures whether to use TLS. Possible values: `prefer`, `disable`, `require` | | `sslcert` | No | | Path of the server certificate. Certificate paths are [resolved relative to the `./prisma folder`](/orm/prisma-schema/overview/data-sources#securing-database-connections) | | `sslrootcert` | No | | Path of the root certificate. Certificate paths are [resolved relative to the `./prisma folder`](/orm/prisma-schema/overview/data-sources#securing-database-connections) | | `sslidentity` | No | | Path to the PKCS12 certificate | | `sslpassword` | No | | Password that was used to secure the PKCS12 file | | `sslaccept` | No | `accept_invalid_certs` | Configures whether to check for missing values in the certificate. Possible values: `accept_invalid_certs`, `strict` | | `host` | No | | Points to a directory that contains a socket to be used for the connection | | `socket_timeout` | No | | Maximum number of seconds to wait until a single query terminates | | `pgbouncer` | No | `false` | Configure the Engine to [enable PgBouncer compatibility mode](/orm/prisma-client/setup-and-configuration/databases-connections/pgbouncer) | | `statement_cache_size` | No | `100` | Since 2.1.0: Specifies the number of [prepared statements](#prepared-statement-caching) cached per connection | | `application_name` | No | | Since 3.3.0: Specifies a value for the application_name configuration parameter | | `channel_binding` | No | `prefer` | Since 4.8.0: Specifies a value for the channel_binding configuration parameter | | `options` | No | | Since 3.8.0: Specifies command line options to send to the server at connection start | As an example, if you want to connect to a schema called `myschema`, set the connection pool size to `5` and configure a timeout for queries of `3` seconds. You can use the following arguments: ``` postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=myschema&connection_limit=5&socket_timeout=3 ``` ### Configuring an SSL connection You can add various parameters to the connection URL if your database server uses SSL. Here's an overview of the possible parameters: - `sslmode=(disable|prefer|require)`: - `prefer` (default): Prefer TLS if possible, accept plain text connections. - `disable`: Do not use TLS. - `require`: Require TLS or fail if not possible. - `sslcert=`: Path to the server certificate. This is the root certificate used by the database server to sign the client certificate. You need to provide this if the certificate doesn't exist in the trusted certificate store of your system. For Google Cloud this likely is `server-ca.pem`. Certificate paths are [resolved relative to the `./prisma folder`](/orm/prisma-schema/overview/data-sources#securing-database-connections) - `sslidentity=`: Path to the PKCS12 certificate database created from client cert and key. This is the SSL identity file in PKCS12 format which you will generate using the client key and client certificate. It combines these two files in a single file and secures them via a password (see next parameter). You can create this file using your client key and client certificate by using the following command (using `openssl`): ``` openssl pkcs12 -export -out client-identity.p12 -inkey client-key.pem -in client-cert.pem ``` - `sslpassword=`: Password that was used to secure the PKCS12 file. The `openssl` command listed in the previous step will ask for a password while creating the PKCS12 file, you will need to provide that same exact password here. - `sslaccept=(strict|accept_invalid_certs)`: - `strict`: Any missing value in the certificate will lead to an error. For Google Cloud, especially if the database doesn't have a domain name, the certificate might miss the domain/IP address, causing an error when connecting. - `accept_invalid_certs` (default): Bypass this check. Be aware of the security consequences of this setting. Your database connection URL will look similar to this: ``` postgresql://USER:PASSWORD@HOST:PORT/DATABASE?sslidentity=client-identity.p12&sslpassword=mypassword&sslcert=rootca.cert ``` ### Connecting via sockets To connect to your PostgreSQL database via sockets, you must add a `host` field as a _query parameter_ to the connection URL (instead of setting it as the `host` part of the URI). The value of this parameter then must point to the directory that contains the socket, e.g.: `postgresql://USER:PASSWORD@localhost/database?host=/var/run/postgresql/` Note that `localhost` is required, the value itself is ignored and can be anything. > **Note**: You can find additional context in this [GitHub issue](https://github.com/prisma/prisma-client-js/issues/437#issuecomment-592436707). ## Type mapping between PostgreSQL and Prisma schema These two tables show the type mapping between PostgreSQL and Prisma schema. First [how Prisma ORM scalar types are translated into PostgreSQL database column types](#mapping-between-prisma-orm-scalar-types-and-postgresql-database-column-types), and then [how PostgreSQL database column types relate to Prisma ORM scalar and native types](#mapping-between-postgresql-database-column-types-to-prisma-orm-scalar-and-native-types). > Alternatively, see [Prisma schema reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) for type mappings organized by Prisma type. ### Mapping between Prisma ORM scalar types and PostgreSQL database column types The PostgreSQL connector maps the [scalar types](/orm/prisma-schema/data-model/models#scalar-fields) from the Prisma ORM [data model](/orm/prisma-schema/data-model/models) as follows to database column types: | Prisma ORM | PostgreSQL | | ---------- | ------------------ | | `String` | `text` | | `Boolean` | `boolean` | | `Int` | `integer` | | `BigInt` | `bigint` | | `Float` | `double precision` | | `Decimal` | `decimal(65,30)` | | `DateTime` | `timestamp(3)` | | `Json` | `jsonb` | | `Bytes` | `bytea` | ### Mapping between PostgreSQL database column types to Prisma ORM scalar and native types - When [introspecting](/orm/prisma-schema/introspection) a PostgreSQL database, the database types are mapped to Prisma ORM types according to the following table. - When [creating a migration](/orm/prisma-migrate) or [prototyping your schema](/orm/prisma-migrate/workflows/prototyping-your-schema) the table is also used - in the other direction. | PostgreSQL (Type \| Aliases) | Supported | Prisma ORM | Native database type attribute | Notes | | ------------------------------------------- | :-------: | ------------- | :--------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `bigint` \| `int8` | ✔️ | `BigInt` | `@db.BigInt`\* | \*Default mapping for `BigInt` - no type attribute added to schema. | | `boolean` \| `bool` | ✔️ | `Bool` | `@db.Boolean`\* | \*Default mapping for `Bool` - no type attribute added to schema. | | `timestamp with time zone` \| `timestamptz` | ✔️ | `DateTime` | `@db.Timestamptz(x)` | | `time without time zone` \| `time` | ✔️ | `DateTime` | `@db.Time(x)` | | `time with time zone` \| `timetz` | ✔️ | `DateTime` | `@db.Timetz(x)` | | `numeric(p,s)` \| `decimal(p,s)` | ✔️ | `Decimal` | `@db.Decimal(x, y)` | | `real` \| `float`, `float4` | ✔️ | `Float` | `@db.Real` | | `double precision` \| `float8` | ✔️ | `Float` | `@db.DoublePrecision`\* | \*Default mapping for `Float` - no type attribute added to schema. | | `smallint` \| `int2` | ✔️ | `Int` | `@db.SmallInt` | | | `integer` \| `int`, `int4` | ✔️ | `Int` | `@db.Int`\* | \*Default mapping for `Int` - no type attribute added to schema. | | `smallserial` \| `serial2` | ✔️ | `Int` | `@db.SmallInt @default(autoincrement())` | | `serial` \| `serial4` | ✔️ | `Int` | `@db.Int @default(autoincrement())` | | `bigserial` \| `serial8` | ✔️ | `Int` | `@db.BigInt @default(autoincrement()` | | `character(n)` \| `char(n)` | ✔️ | `String` | `@db.Char(x)` | | `character varying(n)` \| `varchar(n)` | ✔️ | `String` | `@db.VarChar(x)` | | `money` | ✔️ | `Decimal` | `@db.Money` | | `text` | ✔️ | `String` | `@db.Text`\* | \*Default mapping for `String` - no type attribute added to schema. | | `timestamp` | ✔️ | `DateTime` | `@db.TimeStamp`\* | \*Default mapping for `DateTime` - no type attribute added to schema. | | `date` | ✔️ | `DateTime` | `@db.Date` | | `enum` | ✔️ | `Enum` | N/A | | `inet` | ✔️ | `String` | `@db.Inet` | | `bit(n)` | ✔️ | `String` | `@Bit(x)` | | `bit varying(n)` | ✔️ | `String` | `@VarBit` | | `oid` | ✔️ | `Int` | `@db.Oid` | | `uuid` | ✔️ | `String` | `@db.Uuid` | | `json` | ✔️ | `Json` | `@db.Json` | | `jsonb` | ✔️ | `Json` | `@db.JsonB`\* | \*Default mapping for `Json` - no type attribute added to schema. | | `bytea` | ✔️ | `Bytes` | `@db.ByteA`\* | \*Default mapping for `Bytes` - no type attribute added to schema. | | `xml` | ✔️ | `String` | `@db.Xml` | | Array types | ✔️ | `[]` | | `citext` | ✔️\* | `String` | `@db.Citext` | \* Only available if [Citext extension is enabled](/orm/prisma-schema/data-model/unsupported-database-features#enable-postgresql-extensions-for-native-database-functions). | | `interval` | Not yet | `Unsupported` | | | | `cidr` | Not yet | `Unsupported` | | | | `macaddr` | Not yet | `Unsupported` | | | | `tsvector` | Not yet | `Unsupported` | | | | `tsquery` | Not yet | `Unsupported` | | | | `int4range` | Not yet | `Unsupported` | | | | `int8range` | Not yet | `Unsupported` | | | | `numrange` | Not yet | `Unsupported` | | | | `tsrange` | Not yet | `Unsupported` | | | | `tstzrange` | Not yet | `Unsupported` | | | | `daterange` | Not yet | `Unsupported` | | | | `point` | Not yet | `Unsupported` | | | | `line` | Not yet | `Unsupported` | | | | `lseg` | Not yet | `Unsupported` | | | | `box` | Not yet | `Unsupported` | | | | `path` | Not yet | `Unsupported` | | | | `polygon` | Not yet | `Unsupported` | | | | `circle` | Not yet | `Unsupported` | | | | Composite types | Not yet | n/a | | | | Domain types | Not yet | n/a | | | [Introspection](/orm/prisma-schema/introspection) adds native database types that are **not yet supported** as [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) fields: ```prisma file=schema.prisma showLineNumbers model Device { id Int @id @default(autoincrement()) name String data Unsupported("circle") } ``` ## Prepared statement caching A [prepared statement](https://www.postgresql.org/docs/current/sql-prepare.html) is a feature that can be used to optimize performance. A prepared statement is parsed, compiled, and optimized only once and then can be executed directly multiple times without the overhead of parsing the query again. By caching prepared statements, Prisma Client's [query engine](/orm/more/under-the-hood/engines) does not repeatedly compile the same query which reduces database CPU usage and query latency. For example, here is the generated SQL for two different queries made by Prisma Client: ```sql SELECT * FROM user WHERE name = "John"; SELECT * FROM user WHERE name = "Brenda"; ``` The two queries after parameterization will be the same, and the second query can skip the preparing step, saving database CPU and one extra roundtrip to the database. Query after parameterization: ```sql SELECT * FROM user WHERE name = $1 ``` Every database connection maintained by Prisma Client has a separate cache for storing prepared statements. The size of this cache can be tweaked with the `statement_cache_size` parameter in the connection string. By default, Prisma Client caches `100` statements per connection. Due to the nature of pgBouncer, if the `pgbouncer` parameter is set to `true`, the prepared statement cache is automatically disabled for that connection. --- # MySQL/MariaDB URL: https://www.prisma.io/docs/orm/overview/databases/mysql The MySQL data source connector connects Prisma ORM to a [MySQL](https://www.mysql.com/) or [MariaDB](https://mariadb.org/) database server. By default, the MySQL connector contains a database driver responsible for connecting to your database. You can use a [driver adapter](/orm/overview/databases/database-drivers#driver-adapters) (Preview) to connect to your database using a JavaScript database driver from Prisma Client. ## Example To connect to a MySQL database server, you need to configure a [`datasource`](/orm/prisma-schema/overview/data-sources) block in your [Prisma schema](/orm/prisma-schema): ```prisma file=schema.prisma showLineNumbers datasource db { provider = "mysql" url = env("DATABASE_URL") } ``` The fields passed to the `datasource` block are: - `provider`: Specifies the `mysql` data source connector, which is used both for MySQL and MariaDB. - `url`: Specifies the [connection URL](#connection-url) for the MySQL database server. In this case, an [environment variable is used](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the connection URL. ## Connection details ### Connection URL Here's an overview of the components needed for a MySQL connection URL: ![Structure of the MySQL connection URL](./mysql-connection-string.png) #### Base URL and path Here is an example of the structure of the _base URL_ and the _path_ using placeholder values in uppercase letters: ``` mysql://USER:PASSWORD@HOST:PORT/DATABASE ``` The following components make up the _base URL_ of your database, they are always required: | Name | Placeholder | Description | | :------- | :---------- | :------------------------------------------------------------------------------------------------------------------ | | Host | `HOST` | IP address/domain of your database server, e.g. `localhost` | | Port | `PORT` | Port on which your database server is running, e.g. `5432` (default is `3306`, or no port when using Unix socket) | | User | `USER` | Name of your database user, e.g. `janedoe` | | Password | `PASSWORD` | Password for your database user | | Database | `DATABASE` | Name of the [database](https://dev.mysql.com/doc/refman/8.0/en/creating-database.html) you want to use, e.g. `mydb` | You must [percentage-encode special characters](/orm/reference/connection-urls#special-characters). #### Arguments A connection URL can also take arguments. Here is the same example from above with placeholder values in uppercase letters for three _arguments_: ``` mysql://USER:PASSWORD@HOST:PORT/DATABASE?KEY1=VALUE&KEY2=VALUE&KEY3=VALUE ``` The following arguments can be used: | Argument name | Required | Default | Description | | :----------------- | :------- | ---------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `connection_limit` | No | `num_cpus * 2 + 1` | Maximum size of the [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool) | | `connect_timeout` | No | `5` | Maximum number of seconds to wait for a new connection to be opened, `0` means no timeout | | `pool_timeout` | No | `10` | Maximum number of seconds to wait for a new connection from the pool, `0` means no timeout | | `sslcert` | No | | Path to the server certificate. Certificate paths are [resolved relative to the `./prisma folder`](/orm/prisma-schema/overview/data-sources#securing-database-connections) | | `sslidentity` | No | | Path to the PKCS12 certificate | | `sslpassword` | No | | Password that was used to secure the PKCS12 file | | `sslaccept` | No | `accept_invalid_certs` | Configures whether to check for missing values in the certificate. Possible values: `accept_invalid_certs`, `strict` | | `socket` | No | | Points to a directory that contains a socket to be used for the connection | | `socket_timeout` | No | | Number of seconds to wait until a single query terminates | As an example, if you want to set the connection pool size to `5` and configure a timeout for queries of `3` seconds, you can use the following arguments: ``` mysql://USER:PASSWORD@HOST:PORT/DATABASE?connection_limit=5&socket_timeout=3 ``` ### Configuring an SSL connection You can add various parameters to the connection URL if your database server uses SSL. Here's an overview of the possible parameters: - `sslcert=`: Path to the server certificate. This is the root certificate used by the database server to sign the client certificate. You need to provide this if the certificate doesn't exist in the trusted certificate store of your system. For Google Cloud this likely is `server-ca.pem`. Certificate paths are [resolved relative to the `./prisma folder`](/orm/prisma-schema/overview/data-sources#securing-database-connections) - `sslidentity=`: Path to the PKCS12 certificate database created from client cert and key. This is the SSL identity file in PKCS12 format which you will generate using the client key and client certificate. It combines these two files in a single file and secures them via a password (see next parameter). You can create this file using your client key and client certificate by using the following command (using `openssl`): ``` openssl pkcs12 -export -out client-identity.p12 -inkey client-key.pem -in client-cert.pem ``` - `sslpassword=`: Password that was used to secure the PKCS12 file. The `openssl` command listed in the previous step will ask for a password while creating the PKCS12 file, you will need to provide that same exact password here. - `sslaccept=(strict|accept_invalid_certs)`: - `strict`: Any missing value in the certificate will lead to an error. For Google Cloud, especially if the database doesn't have a domain name, the certificate might miss the domain/IP address, causing an error when connecting. - `accept_invalid_certs` (default): Bypass this check. Be aware of the security consequences of this setting. Your database connection URL will look similar to this: ``` mysql://USER:PASSWORD@HOST:PORT/DATABASE?sslidentity=client-identity.p12&sslpassword=mypassword&sslcert=rootca.cert ``` ### Connecting via sockets To connect to your MySQL/MariaDB database via a socket, you must add a `socket` field as a _query parameter_ to the connection URL (instead of setting it as the `host` part of the URI). The value of this parameter then must point to the directory that contains the socket, e.g. on a default installation of MySQL/MariaDB on Ubuntu or Debian use: `mysql://USER:PASSWORD@HOST/DATABASE?socket=/run/mysqld/mysqld.sock` Note that `localhost` is required, the value itself is ignored and can be anything. > **Note**: You can find additional context in this [GitHub issue](https://github.com/prisma/prisma-client-js/issues/437#issuecomment-592436707). ## Type mapping between MySQL to Prisma schema The MySQL connector maps the [scalar types](/orm/prisma-schema/data-model/models#scalar-fields) from the Prisma ORM [data model](/orm/prisma-schema/data-model/models) as follows to native column types: > Alternatively, see [Prisma schema reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) for type mappings organized by Prisma ORM type. ### Native type mapping from Prisma ORM to MySQL | Prisma ORM | MySQL | Notes | | ---------- | ---------------- | ------------------------------------------------------------------------------------- | | `String` | `VARCHAR(191)` | | | `Boolean` | `BOOLEAN` | In MySQL `BOOLEAN` is a synonym for `TINYINT(1)` | | `Int` | `INT` | | | `BigInt` | `BIGINT` | | | `Float` | `DOUBLE` | | | `Decimal` | `DECIMAL(65,30)` | | | `DateTime` | `DATETIME(3)` | Currently, Prisma ORM does not support zero dates (`0000-00-00`, `00:00:00`) in MySQL | | `Json` | `JSON` | Supported in MySQL 5.7+ only | | `Bytes` | `LONGBLOB` | | ### Native type mapping from Prisma ORM to MariaDB | Prisma ORM | MariaDB | Notes | | ---------- | ---------------- | -------------------------------------------------- | | `String` | `VARCHAR(191)` | | | `Boolean` | `BOOLEAN` | In MariaDB `BOOLEAN` is a synonym for `TINYINT(1)` | | `Int` | `INT` | | | `BigInt` | `BIGINT` | | | `Float` | `DOUBLE` | | | `Decimal` | `DECIMAL(65,30)` | | | `DateTime` | `DATETIME(3)` | | | `Json` | `LONGTEXT` | See https://mariadb.com/kb/en/json-data-type/ | | `Bytes` | `LONGBLOB` | | ### Native type mappings When introspecting a MySQL database, the database types are mapped to Prisma ORM according to the following table: | MySQL | Prisma ORM | Supported | Native database type attribute | Notes | | ------------------------- | ------------- | --------- | ---------------------------------------------- | ------------------------------------------------------------------ | | `serial` | `BigInt` | ✔️ | `@db.UnsignedBigInt @default(autoincrement())` | | `bigint` | `BigInt` | ✔️ | `@db.BigInt` | | `bigint unsigned` | `BigInt` | ✔️ | `@db.UnsignedBigInt` | | `bit` | `Bytes` | ✔️ | `@db.Bit(x)` | `bit(1)` maps to `Boolean` - all other `bit(x)` map to `Bytes` | | `boolean` \| `tinyint(1)` | `Boolean` | ✔️ | `@db.TinyInt(1)` | | `varbinary` | `Bytes` | ✔️ | `@db.VarBinary` | | `longblob` | `Bytes` | ✔️ | `@db.LongBlob` | | `tinyblob` | `Bytes` | ✔️ | `@db.TinyBlob` | | `mediumblob` | `Bytes` | ✔️ | `@db.MediumBlob` | | `blob` | `Bytes` | ✔️ | `@db.Blob` | | `binary` | `Bytes` | ✔️ | `@db.Binary` | | `date` | `DateTime` | ✔️ | `@db.Date` | | `datetime` | `DateTime` | ✔️ | `@db.DateTime` | | `timestamp` | `DateTime` | ✔️ | `@db.TimeStamp` | | `time` | `DateTime` | ✔️ | `@db.Time` | | `decimal(a,b)` | `Decimal` | ✔️ | `@db.Decimal(x,y)` | | `numeric(a,b)` | `Decimal` | ✔️ | `@db.Decimal(x,y)` | | `enum` | `Enum` | ✔️ | N/A | | `float` | `Float` | ✔️ | `@db.Float` | | `double` | `Float` | ✔️ | `@db.Double` | | `smallint` | `Int` | ✔️ | `@db.SmallInt` | | `smallint unsigned` | `Int` | ✔️ | `@db.UnsignedSmallInt` | | `mediumint` | `Int` | ✔️ | `@db.MediumInt` | | `mediumint unsigned` | `Int` | ✔️ | `@db.UnsignedMediumInt` | | `int` | `Int` | ✔️ | `@db.Int` | | `int unsigned` | `Int` | ✔️ | `@db.UnsignedInt` | | `tinyint` | `Int` | ✔️ | `@db.TinyInt(x)` | `tinyint(1)` maps to `Boolean` all other `tinyint(x)` map to `Int` | | `tinyint unsigned` | `Int` | ✔️ | `@db.UnsignedTinyInt(x)` | `tinyint(1) unsigned` **does not** map to `Boolean` | | `year` | `Int` | ✔️ | `@db.Year` | | `json` | `Json` | ✔️ | `@db.Json` | Supported in MySQL 5.7+ only | | `char` | `String` | ✔️ | `@db.Char(x)` | | `varchar` | `String` | ✔️ | `@db.VarChar(x)` | | `tinytext` | `String` | ✔️ | `@db.TinyText` | | `text` | `String` | ✔️ | `@db.Text` | | `mediumtext` | `String` | ✔️ | `@db.MediumText` | | `longtext` | `String` | ✔️ | `@db.LongText` | | `set` | `Unsupported` | Not yet | | | `geometry` | `Unsupported` | Not yet | | | `point` | `Unsupported` | Not yet | | | `linestring` | `Unsupported` | Not yet | | | `polygon` | `Unsupported` | Not yet | | | `multipoint` | `Unsupported` | Not yet | | | `multilinestring` | `Unsupported` | Not yet | | | `multipolygon` | `Unsupported` | Not yet | | | `geometrycollection` | `Unsupported` | Not yet | | [Introspection](/orm/prisma-schema/introspection) adds native database types that are **not yet supported** as [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) fields: ```prisma file=schema.prisma showLineNumbers model Device { id Int @id @default(autoincrement()) name String data Unsupported("circle") } ``` ## Engine If you are using a version of MySQL where MyISAM is the default engine, you must specify `ENGINE = InnoDB;` when you create a table. If you introspect a database that uses a different engine, relations in the Prisma Schema are not created (or lost, if the relation already existed). ## Permissions A fresh new installation of MySQL/MariaDB has by default only a `root` database user. Do not use `root` user in your Prisma configuration, but instead create a database and database user for each application. On most Linux hosts (e.g. Ubuntu) you can simply run this as the Linux `root` user (which automatically has database `root` access as well): ``` mysql -e "CREATE DATABASE IF NOT EXISTS $DB_PRISMA;" mysql -e "GRANT ALL PRIVILEGES ON $DB_PRISMA.* TO $DB_USER@'%' IDENTIFIED BY '$DB_PASSWORD';" ``` The above is enough to run the `prisma db pull` and `prisma db push` commands. In order to also run `prisma migrate` commands these permissions need to be granted: ``` mysql -e "GRANT CREATE, DROP, REFERENCES, ALTER ON *.* TO $DB_USER@'%';" ``` --- # SQLite URL: https://www.prisma.io/docs/orm/overview/databases/sqlite The SQLite data source connector connects Prisma ORM to a [SQLite](https://www.sqlite.org/) database file. These files always have the file ending `.db` (e.g.: `dev.db`). By default, the SQLite connector contains a database driver responsible for connecting to your database. You can use a [driver adapter](/orm/overview/databases/database-drivers#driver-adapters) (Preview) to connect to your database using a JavaScript database driver from Prisma Client. ## Example To connect to a SQLite database file, you need to configure a [`datasource`](/orm/prisma-schema/overview/data-sources) block in your [Prisma schema](/orm/prisma-schema): ```prisma file=schema.prisma datasource db { provider = "sqlite" url = "file:./dev.db" } ``` The fields passed to the `datasource` block are: - `provider`: Specifies the `sqlite` data source connector. - `url`: Specifies the [connection URL](/orm/reference/connection-urls) for the SQLite database. The connection URL always starts with the prefix `file:` and then contains a file path pointing to the SQLite database file. In this case, the file is located in the same directory and called `dev.db`. ## Type mapping between SQLite to Prisma schema The SQLite connector maps the [scalar types](/orm/prisma-schema/data-model/models#scalar-fields) from the [data model](/orm/prisma-schema/data-model/models) to native column types as follows: > Alternatively, see [Prisma schema reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) for type mappings organized by Prisma ORM type. ### Native type mapping from Prisma ORM to SQLite | Prisma ORM | SQLite | | ---------- | ------------- | | `String` | `TEXT` | | `Boolean` | `BOOLEAN` | | `Int` | `INTEGER` | | `BigInt` | `INTEGER` | | `Float` | `REAL` | | `Decimal` | `DECIMAL` | | `DateTime` | `NUMERIC` | | `Json` | `JSONB` | | `Bytes` | `BLOB` | | `Enum` | `TEXT` | :::note SQLite doesn't have a dedicated Boolean type. While this table shows `BOOLEAN`, columns are assigned a **NUMERIC affinity** (storing `0` for false and `1` for true). [Learn more](https://www.sqlite.org/datatype3.html#boolean). ::: :::warning When using `enum` fields in SQLite, be aware of the following: - **No database-level enforcement for correctness**: If you bypass Prisma ORM and store an invalid enum entry in the database, Prisma Client queries will fail at runtime when reading that entry. - **No migration-level enforcement for correctness**: It's possible to end up with incorrect data after schema changes similarly to MongoDB (since the enums aren't checked by the database). ::: ## Rounding errors on big numbers SQLite is a loosely-typed database. If your Schema has a field of type `Int`, then Prisma ORM prevents you from inserting a value larger than an integer. However, nothing prevents the database from directly accepting a bigger number. These manually-inserted big numbers cause rounding errors when queried. To avoid this problem, Prisma ORM 4.0.0 and later checks numbers on the way out of the database to verify that they fit within the boundaries of an integer. If a number does not fit, then Prisma ORM throws a P2023 error, such as: ``` Inconsistent column data: Conversion failed: Value 9223372036854775807 does not fit in an INT column, try migrating the 'int' column type to BIGINT ``` ## Connection details ### Connection URL The connection URL of a SQLite connector points to a file on your file system. For example, the following two paths are equivalent because the `.db` is in the same directory: ```prisma file=schema.prisma showLineNumbers datasource db { provider = "sqlite" url = "file:./dev.db" } ``` is the same as: ```prisma file=schema.prisma showLineNumbers datasource db { provider = "sqlite" url = "file:dev.db" } ``` You can also target files from the root or any other place in your file system: ```prisma file=schema.prisma showLineNumbers datasource db { provider = "sqlite" url = "file:/Users/janedoe/dev.db" } ``` --- # MongoDB URL: https://www.prisma.io/docs/orm/overview/databases/mongodb This guide discusses the concepts behind using Prisma ORM and MongoDB, explains the commonalities and differences between MongoDB and other database providers, and leads you through the process for configuring your application to integrate with MongoDB using Prisma ORM. To connect Prisma ORM with MongoDB, refer to our [Getting Started documentation](/getting-started/setup-prisma/start-from-scratch/mongodb-typescript-mongodb). ## What is MongoDB? [MongoDB](https://www.mongodb.com/) is a NoSQL database that stores data in [BSON](https://bsonspec.org/) format, a JSON-like document format designed for storing data in key-value pairs. It is commonly used in JavaScript application development because the document model maps easily to objects in application code, and there is built in support for high availability and horizontal scaling. MongoDB stores data in collections that do not need a schema to be defined in advance, as you would need to do with tables in a relational database. The structure of each collection can also be changed over time. This flexibility can allow rapid iteration of your data model, but it does mean that there are a number of differences when using Prisma ORM to work with your MongoDB database. ## Commonalities with other database providers Some aspects of using Prisma ORM with MongoDB are the same as when using Prisma ORM with a relational database. You can still: - model your database with the [Prisma Schema Language](/orm/prisma-schema) - connect to your database, using the [`mongodb` database connector](/orm/overview/databases) - use [Introspection](/orm/prisma-schema/introspection) for existing projects if you already have a MongoDB database - use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) to push changes in your schema to the database - use [Prisma Client](/orm/prisma-client) in your application to query your database in a type safe way based on your Prisma Schema ## Differences to consider MongoDB's document-based structure and flexible schema means that using Prisma ORM with MongoDB differs from using it with a relational database in a number of ways. These are some areas where there are differences that you need to be aware of: - **Defining IDs**: MongoDB documents have an `_id` field (that often contains an [ObjectID](https://www.mongodb.com/docs/manual/reference/bson-types/#std-label-objectid)). Prisma ORM does not support fields starting with `_`, so this needs to be mapped to a Prisma ORM field using the `@map` attribute. For more information, see [Defining IDs in MongoDB](/orm/prisma-schema/data-model/models#defining-ids-in-mongodb). - **Migrating existing data to match your Prisma schema**: In relational databases, all your data must match your schema. If you change the type of a particular field in your schema when you migrate, all the data must also be updated to match. In contrast, MongoDB does not enforce any particular schema, so you need to take care when migrating. For more information, see [How to migrate old data to new schemas](#how-to-migrate-existing-data-to-match-your-prisma-schema). - **Introspection and Prisma ORM relations**: When you introspect an existing MongoDB database, you will get a schema with no relations and will need to add the missing relations in manually. For more information, see [How to add in missing relations after Introspection](#how-to-add-in-missing-relations-after-introspection). - **Filtering for `null` and missing fields**: MongoDB makes a distinction between setting a field to `null` and not setting it at all, which is not present in relational databases. Prisma ORM currently does not express this distinction, which means that you need to be careful when filtering for `null` and missing fields. For more information, see [How to filter for `null` and missing fields](#how-to-filter-for-null-and-missing-fields) - **Enabling replication**: Prisma ORM uses [MongoDB transactions](https://www.mongodb.com/docs/manual/core/transactions/) internally to avoid partial writes on nested queries. When using transactions, MongoDB requires replication of your data set to be enabled. To do this, you will need to configure a [replica set](https://www.mongodb.com/docs/manual/replication/) — this is a group of MongoDB processes that maintain the same data set. Note that it is still possible to use a single database, by creating a replica set with only one node in it. If you use MongoDB's [Atlas](https://www.mongodb.com/atlas/database) hosting service, the replica set is configured for you, but if you are running MongoDB locally you will need to set up a replica set yourself. For more information, see MongoDB's [guide to deploying a replica set](https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/). ### Performance considerations for large collections #### Problem When working with large MongoDB collections through Prisma, certain operations can become slow and resource-intensive. In particular, operations that require scanning the entire collection, such as `count()`, can hit query execution time limits and significantly impact performance as your dataset grows. #### Solution To address performance issues with large MongoDB collections, consider the following approaches: 1. For large collections, consider using MongoDB's `estimatedDocumentCount()` instead of `count()`. This method is much faster as it uses metadata about the collection. You can use Prisma's `runCommandRaw` method to execute this command. 2. For frequently accessed counts, consider implementing a counter cache. This involves maintaining a separate document with pre-calculated counts that you update whenever documents are added or removed. ## How to use Prisma ORM with MongoDB This section provides instructions for how to carry out tasks that require steps specific to MongoDB. ### How to migrate existing data to match your Prisma schema Migrating your database over time is an important part of the development cycle. During development, you will need to update your Prisma schema (for example, to add new fields), then update the data in your development environment’s database, and eventually push both the updated schema and the new data to the production database. When using MongoDB, be aware that the “coupling” between your schema and the database is purposefully designed to be less rigid than with SQL databases; MongoDB will not enforce the schema, so you have to verify data integrity. These iterative tasks of updating the schema and the database can result in inconsistencies between your schema and the actual data in the database. Let’s look at one scenario where this can happen, and then examine several strategies for you and your team to consider for handling these inconsistencies. **Scenario**: you need to include a phone number for users, as well as an email. You currently have the following `User` model in your `schema.prisma` file: ```prisma file=prisma/schema.prisma showLineNumbers model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String } ``` There are a number of strategies you could use for migrating this schema: - **"On-demand" updates**: with this strategy, you and your team have agreed that updates can be made to the schema as needed. However, in order to avoid migration failures due to inconsistencies between the data and schema, there is agreement in the team that any new fields added are explicitly defined as optional. In our scenario above, you can add an optional `phoneNumber` field to the `User` model in your Prisma schema: ```prisma file=prisma/schema.prisma highlight=4;add showLineNumbers model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String //add-next-line phoneNumber String? } ``` Then regenerate your Prisma Client using the `npx prisma generate` command. Next, update your application to reflect the new field, and redeploy your app. As the `phoneNumber` field is optional, you can still query the old users where the phone number has not been defined. The records in the database will be updated "on demand" as the application's users begin to enter their phone number in the new field. Another option is to add a default value on a required field, for example: ```prisma file=prisma/schema.prisma highlight=4;add showLineNumbers model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String //add-next-line phoneNumber String @default("000-000-0000") } ``` Then when you encounter a missing `phoneNumber`, the value will be coerced into `000-000-0000`. - **"No breaking changes" updates**: this strategy builds on the first one, with further consensus amongst your team that you don't rename or delete fields, only add new fields, and always define the new fields as optional. This policy can be reinforced by adding checks in the CI/CD process to verify that there are no backwards-incompatible changes to the schema. - **"All-at-once" updates**: this strategy is similar to traditional migrations in relational databases, where all data is updated to reflect the new schema. In the scenario above, you would create a script to add a value for the phone number field to all existing users in your database. You can then make the field a required field in the application because the schema and the data are consistent. ### How to add in missing relations after Introspection After introspecting an existing MongoDB database, you will need to manually add in relations between models. MongoDB does not have the concept of defining relations via foreign keys, as you would in a relational database. However, if you have a collection in MongoDB with a "foreign-key-like" field that matches the ID field of another collection, Prisma ORM will allow you to emulate relations between the collections. As an example, take a MongoDB database with two collections, `User` and `Post`. The data in these collections has the following format, with a `userId` field linking users to posts: `User` collection: - `_id` field with a type of `objectId` - `email` field with a type of `string` `Post` collection: - `_id` field with a type of `objectId` - `title` field with a type of `string` - `userId` with a type of `objectID` On introspection with `db pull`, this is pulled in to the Prisma Schema as follows: ```prisma file=prisma/schema.prisma showLineNumbers model Post { id String @id @default(auto()) @map("_id") @db.ObjectId title String userId String @db.ObjectId } model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String } ``` This is missing the relation between the `User` and `Post` models. To fix this, manually add a `user` field to the `Post` model with a `@relation` attribute using `userId` as the `fields` value, linking it to the `User` model, and a `posts` field to the `User` model as the back relation: ```prisma file=prisma/schema.prisma highlight=5;add|11;add showLineNumbers model Post { id String @id @default(auto()) @map("_id") @db.ObjectId title String userId String @db.ObjectId //add-next-line user User @relation(fields: [userId], references: [id]) } model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String //add-next-line posts Post[] } ``` For more information on how to use relations in Prisma ORM, see [our documentation](/orm/prisma-schema/data-model/relations). ### How to filter for `null` and missing fields To understand how MongoDB distinguishes between `null` and missing fields, consider the example of a `User` model with an optional `name` field: ```ts model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String name String? } ``` First, try creating a record with the `name` field explicitly set to `null`. Prisma ORM will return `name: null` as expected: ```ts const createNull = await prisma.user.create({ data: { email: 'user1@prisma.io', name: null, }, }) console.log(createNull) ``` ```code no-copy { id: '6242c4ae032bc76da250b207', email: 'user1@prisma.io', name: null } ``` If you check your MongoDB database directly, you will also see a new record with `name` set to `null`: ```json { "_id": "6242c4af032bc76da250b207", "email": "user1@prisma.io", "name": null } ``` Next, try creating a record without explicitly setting the `name` field: ```ts const createMissing = await prisma.user.create({ data: { email: 'user2@prisma.io', }, }) console.log(createMissing) ``` ```code no-copy { id: '6242c4ae032bc76da250b208', email: 'user2@prisma.io', name: null } ``` Prisma ORM still returns `name: null`, but if you look in the database directly you will see that the record has no `name` field defined at all: ```json { "_id": "6242c4af032bc76da250b208", "email": "user2@prisma.io" } ``` Prisma ORM returns the same result in both cases, because we currently don't have a way to specify this difference in MongoDB between fields that are `null` in the underlying database, and fields that are not defined at all — see [this Github issue](https://github.com/prisma/prisma/issues/12555) for more information. This means that you currently have to be careful when filtering for `null` and missing fields. Filtering for records with `name: null` will only return the first record, with the `name` explicitly set to `null`: ```ts const findNulls = await prisma.user.findMany({ where: { name: null, }, }) console.log(findNulls) ``` ```terminal no-copy [ { id: '6242c4ae032bc76da250b207', email: 'user1@prisma.io', name: null } ] ``` This is because `name: null` is checking for equality, and a non-existing field isn't equal to `null`. To include missing fields as well, use the [`isSet` filter](/orm/reference/prisma-client-reference#isset) to explicitly search for fields which are either `null` or not set. This will return both records: ```ts const findNullOrMissing = await prisma.user.findMany({ where: { OR: [ { name: null, }, { name: { isSet: false, }, }, ], }, }) console.log(findNullOrMissing) ``` ```terminal no-copy [ { id: '6242c4ae032bc76da250b207', email: 'user1@prisma.io', name: null }, { id: '6242c4ae032bc76da250b208', email: 'user2@prisma.io', name: null } ] ``` ## More on using MongoDB with Prisma ORM The fastest way to start using MongoDB with Prisma ORM is to refer to our Getting Started documentation: - [Start from scratch](/getting-started/setup-prisma/start-from-scratch/mongodb-typescript-mongodb) - [Add to existing project](/getting-started/setup-prisma/add-to-existing-project/mongodb-typescript-mongodb) These tutorials will take you through the process of connecting to MongoDB, pushing schema changes, and using Prisma Client. Further reference information is available in the [MongoDB connector documentation](/orm/overview/databases/mongodb). For more information on how to set up and manage a MongoDB database, see the [Prisma Data Guide](https://www.prisma.io/dataguide#mongodb). ## Example To connect to a MongoDB server, configure the [`datasource`](/orm/prisma-schema/overview/data-sources) block in your [Prisma Schema](/orm/prisma-schema): ```prisma file=schema.prisma showLineNumbers datasource db { provider = "mongodb" url = env("DATABASE_URL") } ``` The fields passed to the `datasource` block are: - `provider`: Specifies the `mongodb` data source connector. - `url`: Specifies the [connection URL](#connection-url) for the MongoDB server. In this case, an [environment variable is used](/orm/more/development-environment/environment-variables) to provide the connection URL. The MongoDB database connector uses transactions to support nested writes. Transactions **require** a [replica set](https://www.mongodb.com/docs/manual/tutorial/deploy-replica-set/) deployment. The easiest way to deploy a replica set is with [Atlas](https://www.mongodb.com/docs/atlas/getting-started/). It's free to get started. ## Connection details ### Connection URL The MongoDB connection URL can be configured in different ways depending on how you are hosting your database. The standard configuration is made up of the following components: ![Structure of the MongoDB connection URL](./mongodb.png) #### Base URL and path The base URL and path sections of the connection URL are made up of your authentication credentials followed by the host (and optionally, a port number) and database. ``` mongodb://USERNAME:PASSWORD@HOST/DATABASE ``` The following components make up the _base URL_ of your database: | Name | Placeholder | Description | | :------- | :---------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | User | `USERNAME` | Name of your database user, e.g. `janedoe` | | Password | `PASSWORD` | Password for your database user | | Host | `HOST` | The host where a [`mongod`](https://www.mongodb.com/docs/manual/reference/program/mongod/#mongodb-binary-bin.mongod) instance is running. If you are running a sharded cluster this will a [`mongos`](https://www.mongodb.com/docs/manual/reference/program/mongos/#mongodb-binary-bin.mongos) instance. This can be a hostname, IP address or UNIX domain socket. | | Port | `PORT` | Port on which your database server is running, e.g. `1234`. If none is provided the default `27017` is used. | | Database | `DATABASE` | Name of the database to use. If none is specified but the `authSource` option is set then the `authSource` database name is used. If neither the database in the connection string nor the `authSource` option is specified then it defaults to `admin` | You must [percentage-encode special characters](/orm/reference/connection-urls#special-characters). #### Arguments A connection URL can also take arguments. The following example sets three arguments: - An `ssl` connection - A `connectTimeoutMS` - And the `maxPoolSize` ``` mongodb://USERNAME:PASSWORD@HOST/DATABASE?ssl=true&connectTimeoutMS=5000&maxPoolSize=50 ``` Refer to the [MongoDB connection string documentation](https://www.mongodb.com/docs/manual/reference/connection-string/) for a complete list of connection string arguments. There are no Prisma ORM-specific arguments. ## Using `ObjectId` It is common practice for the `_id` field of a MongoDB document to contain an [ObjectId](https://www.mongodb.com/docs/manual/reference/bson-types/#std-label-objectid): ```json { "_id": { "$oid": "60d599cb001ef98000f2cad2" }, "createdAt": { "$date": { "$numberLong": "1624611275577" } }, "email": "ella@prisma.io", "name": "Ella", "role": "ADMIN" } ``` Any field (most commonly IDs and relation scalar fields) that maps to an `ObjectId` in the underlying database: - Must be of type `String` or `Bytes` - Must include the `@db.ObjectId` attribute - Can optionally use `@default(auto())` to auto-generate a valid `ObjectId` on document creation Here is an example that uses `String`: ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId // Other fields } ``` And here is another example that uses `Bytes`: ```prisma model User { id Bytes @id @default(auto()) @map("_id") @db.ObjectId // Other fields } ``` See also: [Defining ID fields in MongoDB](/orm/prisma-schema/data-model/models#defining-ids-in-mongodb) ### Generating `ObjectId` To generate a valid `ObjectId` (for testing purposes or to manually set an ID field value) in your application, use the [`bson`](https://www.npmjs.com/package/bson) package. ``` npm install --save bson ``` ```ts import { ObjectId } from 'bson' const id = new ObjectId() ``` ## Differences to connectors for relational databases This section covers ways in which the MongoDB connector differs from Prisma ORM connectors for relational databases. ### No support for Prisma Migrate Currently, there are no plans to add support for [Prisma Migrate](/orm/prisma-migrate) as MongoDB projects do not rely on internal schemas where changes need to be managed with an extra tool. Management of `@unique` indexes is realized through `db push`. ### No support for `@@id` and `autoincrement()` The [`@@id`](/orm/reference/prisma-schema-reference#id-1) attribute (an ID for multiple fields) is not supported because primary keys in MongoDB are always on the `_id` field of a model. The [`autoincrement()`](/orm/reference/prisma-schema-reference#generate-autoincrementing-integers-as-ids-relational-databases-only) function (which creates incrementing `@id` values) is not supported because `autoincrement()` does not work with the `ObjectID` type that the `_id` field has in MongoDB. ### Cyclic references and referential actions If you have cyclic references in your models, either from self-relations or a cycle of relations between models, and you use [referential actions](/orm/prisma-schema/data-model/relations/referential-actions), you must set a referential action of `NoAction` to prevent an infinite loop of actions. See [Special rules for referential actions](/orm/prisma-schema/data-model/relations/referential-actions/special-rules-for-referential-actions) for more details. ### Replica set configuration MongoDB only allows you to start a transaction on a replica set. Prisma ORM uses transactions internally to avoid partial writes on nested queries. This means we inherit the requirement of needing a replica set configured. When you try to use Prisma ORM's MongoDB connector on a deployment that has no replica set configured, Prisma ORM shows the message `Error: Transactions are not supported by this deployment`. The full text of the error message is the following: ``` PrismaClientUnknownRequestError2 [PrismaClientUnknownRequestError]: Invalid `prisma.post.create()` invocation in /index.ts:9:21 6 await prisma.$connect() 7 8 // Create the first post → 9 await prisma.post.create( Error in connector: Database error. error code: unknown, error message: Transactions are not supported by this deployment at cb (/node_modules/@prisma/client/runtime/index.js:34804:17) at processTicksAndRejections (internal/process/task_queues.js:97:5) { clientVersion: '3.xx.0' } ``` To resolve this, we suggest you change your deployment to one with a replica set configured. One simple way for this is to use [MongoDB Atlas](https://www.mongodb.com/cloud/atlas) to launch a free instance that has replica set support out of the box. There's also an option to run the replica set locally with this guide: https://www.mongodb.com/docs/manual/tutorial/convert-standalone-to-replica-set ## Type mapping between MongoDB and the Prisma schema The MongoDB connector maps the [scalar types](/orm/prisma-schema/data-model/models#scalar-fields) from the Prisma ORM [data model](/orm/prisma-schema/data-model/models) to MongoDB's native column types as follows: > Alternatively, see [Prisma schema reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) for type mappings organized by Prisma type. ### Native type mapping from Prisma ORM to MongoDB | Prisma ORM | MongoDB | | ---------- | ---------------------------------------------------------------------- | | `String` | `string` | | `Boolean` | `bool` | | `Int` | `int` | | `BigInt` | `long` | | `Float` | `double` | | `Decimal` | [Currently unsupported](https://github.com/prisma/prisma/issues/12637) | | `DateTime` | `timestamp` | | `Bytes` | `binData` | | `Json` | | MongoDB types that are currently unsupported: - `Decimal128` - `Undefined` - `DBPointer` - `Null` - `Symbol` - `MinKey` - `MaxKey` - `Object` - `Javascript` - `JavascriptWithScope` - `Regex` ### Mapping from MongoDB to Prisma ORM types on Introspection When introspecting a MongoDB database, Prisma ORM uses the relevant [scalar types](/orm/prisma-schema/data-model/models#scalar-fields). Some special types also get additional native type annotations: | MongoDB (Type \| Aliases) | Prisma ORM | Supported | Native database type attribute | Notes | | ------------------------- | ---------- | :-------: | :----------------------------- | :---- | | `objectId` | `String` | ✔️ | `@db.ObjectId` | | [Introspection](/orm/prisma-schema/introspection) adds native database types that are **not yet supported** as [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) fields: ```prisma file=schema.prisma showLineNumbers model Example { id String @id @default(auto()) @map("_id") @db.ObjectId name String regex Unsupported("RegularExpression") } ``` --- # SQL Server on Windows (local) URL: https://www.prisma.io/docs/orm/overview/databases/sql-server/sql-server-local To run a Microsoft SQL Server locally on a Windows machine: 1. If you do not have access to an instance of Microsoft SQL Server, download and set up [SQL Server 2019 Developer](https://www.microsoft.com/en-us/sql-server/sql-server-downloads). 1. Download and install [SQL Server Management Studio](https://learn.microsoft.com/en-us/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver15). 1. Use Windows Authentication to log in to Microsoft SQL Server Management Studio (expand the **Server Name** dropdown and click **<Browse for more...>** to find your database engine): ![The New Query button in SQL Server Management Studio](/img/orm/connect-sql-server.png) ## Enable TCP/IP Prisma Client requires TCP/IP to be enabled. To enable TCP/IP: 1. Open SQL Server Configuration Manager. (Search for "SQL Server Configuration Manager" in the Start Menu, or open the Start Menu and type "SQL Server Configuration Manager".) 1. In the left-hand panel, click **SQL Server Network Configuration** > **Protocols for MSSQLSERVER** 1. Right-click **TCP/IP** and choose **Enable**. ## Enable authentication with SQL logins (Optional) If you want to use a username and password in your connection URL rather than integrated security, [enable mixed authentication mode](https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/change-server-authentication-mode?view=sql-server-ver15&tabs=ssms) as follows: 1. Right-click on your database engine in the Object Explorer and click **Properties**. 1. In the Server Properties window, click **Security** in the left-hand list and tick the **SQL Server and Windows Authentication Mode** option, then click **OK**. 1. Right-click on your database engine in the Object Explorer and click **Restart**. ### Enable the `sa` login To enable the default `sa` (administrator) SQL Server login: 1. In SQL Server Management Studio, in the Object Explorer, expand **Security** > **Logins** and double-click **sa**. 1. On the **General** page, choose a password for the `sa` account (untick **Enforce password policy** if you do not want to enforce a policy). 1. On the **Status** page, under **Settings** > **Login**, tick **Enabled**, then click **OK**. You can now use the `sa` account in a connection URL and when you log in to SQL Server Management Studio. > **Note**: The `sa` user has extensive permissions. You can also [create your own login with fewer permissions](https://learn.microsoft.com/en-us/sql/relational-databases/security/authentication-access/create-a-login?view=sql-server-ver15). --- # SQL Server on Docker URL: https://www.prisma.io/docs/orm/overview/databases/sql-server/sql-server-docker To run a Microsoft SQL Server container image with Docker: 1. Install and set up [Docker](https://docs.docker.com/get-started/get-docker/) 1. Run the following command in your terminal to download the Microsoft SQL Server 2019 image: ```terminal docker pull mcr.microsoft.com/mssql/server:2019-latest ``` 1. Create an instance of the container image, replacing the value of `SA_PASSWORD` with a password of your choice: ```terminal wrap docker run --name sql_container -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=myPassword' -p 1433:1433 -d mcr.microsoft.com/mssql/server:2019-latest ``` 1. [Follow Microsoft's instructions to connect to SQL Server and use the `sqlcmd` tool](https://learn.microsoft.com/en-us/sql/linux/quickstart-install-connect-docker?view=sql-server-ver15&pivots=cs1-cmd&tabs=cli#connect-to-sql-server), replacing the image name and password with your own. 1. From the `sqlcmd` command prompt, create a new database: ```terminal CREATE DATABASE quickstart GO ``` 1. Run the following command to check that your database was created successfully: ```terminal sp_databases GO ``` ## Connection URL credentials Based on this example, your credentials are: - **Username**: sa - **Password**: myPassword - **Database**: quickstart - **Port**: 1433 --- # Microsoft SQL Server URL: https://www.prisma.io/docs/orm/overview/databases/sql-server/index The Microsoft SQL Server data source connector connects Prisma ORM to a [Microsoft SQL Server](https://learn.microsoft.com/en-us/sql/sql-server/?view=sql-server-ver15) database server. ## Example To connect to a Microsoft SQL Server database, you need to configure a [`datasource`](/orm/prisma-schema/overview/data-sources) block in your [Prisma schema](/orm/prisma-schema): ```prisma file=schema.prisma showLineNumbers datasource db { provider = "sqlserver" url = env("DATABASE_URL") } ``` The fields passed to the `datasource` block are: - `provider`: Specifies the `sqlserver` data source connector. - `url`: Specifies the [connection URL](#connection-details) for the Microsoft SQL Server database. In this case, an [environment variable is used](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the connection URL. ## Connection details The connection URL used to connect to an Microsoft SQL Server database follows the [JDBC standard](https://learn.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver15). The following example uses SQL authentication (username and password) with an enabled TLS encrypted connection: ``` sqlserver://HOST[:PORT];database=DATABASE;user=USER;password=PASSWORD;encrypt=true ``` Note: If you are using any of the following characters in your connection string, [you will need to escape them](https://learn.microsoft.com/en-us/sql/connect/jdbc/building-the-connection-url?view=sql-server-ver16#escaping-values-in-the-connection-url). ```terminal :\=;/[]{} # these are characters that will need to be escaped ``` To escape these characters, use curly braces `{}` around values that contain special characters. As an example: ```terminal sqlserver://HOST[:PORT];database=DATABASE;user={MyServer/MyUser};password={ThisIsA:SecurePassword;};encrypt=true ``` ### Arguments | Argument name | Required | Default | Comments | | :------------------------------------------------------------------------------------ | :---------------- | :----------------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | |
  • `database`
  • `initial catalog`
| No | `master` | The database to connect to. | |
  • `username`
  • `user`
  • `uid`
  • `userid`
| No - see Comments | | SQL Server login (such as `sa`) _or_ a valid Windows (Active Directory) username if `integratedSecurity` is set to `true` (Windows only). | |
  • `password`
  • `pwd`
| No - see Comments | | Password for SQL Server login _or_ Windows (Active Directory) username if `integratedSecurity` is set to `true` (Windows only). | | `encrypt` | No | `true` | Configures whether to use TLS all the time, or only for the login procedure, possible values: `true` (use always), `false` (only for login credentials). | | `integratedSecurity` | No | | Enables [Windows authentication (integrated security)](https://learn.microsoft.com/en-us/previous-versions/dotnet/framework/data/adonet/sql/authentication-in-sql-server), possible values: `true`, `false`, `yes`, `no`. If set to `true` or `yes` and `username` and `password` are present, login is performed through Windows Active Directory. If login details are not given via separate arguments, the current logged in Windows user is used to login to the server. | | `connectionLimit` | No | `num_cpus * 2 + 1` | Maximum size of the [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool) | | `connectTimeout` | No | `5` | Maximum number of seconds to wait for a new connection | | `schema` | No | `dbo` | Added as a prefix to all the queries if schema name is not the default. | |
  • `loginTimeout`
  • `connectTimeout`
  • `connectionTimeout`
| No | | Number of seconds to wait for login to succeed. | | `socketTimeout` | No | | Number of seconds to wait for each query to succeed. | | `isolationLevel` | No | | Sets [transaction isolation level](https://learn.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-ver15). | | `poolTimeout` | No | `10` | Maximum number of seconds to wait for a new connection from the pool. If all connections are in use, the database will return a `PoolTimeout` error after waiting for the given time. | |
  • `ApplicationName`
  • `Application Name`
(case insensitive) | No | | Sets the application name for the connection. Since version 2.28.0. | | `trustServerCertificate` | No | `false` | Configures whether to trust the server certificate. | | `trustServerCertificateCA` | No | | A path to a certificate authority file to be used instead of the system certificates to authorize the server certificate. Must be either in `pem`, `crt` or `der` format. Cannot be used together with `trustServerCertificate` parameter. | ### Using [integrated security](https://learn.microsoft.com/en-us/previous-versions/dotnet/framework/data/adonet/sql/authentication-in-sql-server) (Windows only) The following example uses the currently logged in Windows user to log in to Microsoft SQL Server: ``` sqlserver://localhost:1433;database=sample;integratedSecurity=true;trustServerCertificate=true; ``` The following example uses a specific Active Directory user to log in to Microsoft SQL Server: ``` sqlserver://localhost:1433;database=sample;integratedSecurity=true;username=prisma;password=aBcD1234;trustServerCertificate=true; ``` #### Connect to a named instance The following example connects to a named instance of Microsoft SQL Server (`mycomputer\sql2019`) using integrated security: ``` sqlserver://mycomputer\sql2019;database=sample;integratedSecurity=true;trustServerCertificate=true; ``` ## Type mapping between Microsoft SQL Server to Prisma schema For type mappings organized by Prisma ORM type, refer to the [Prisma schema reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) documentation. ## Supported versions See [Supported databases](/orm/reference/supported-databases). ## Limitations and known issues ### Prisma Migrate caveats Prisma Migrate is supported in [2.13.0](https://github.com/prisma/prisma/releases/tag/2.13.0) and later with the following caveats: #### Database schema names SQL Server does not have an equivalent to the PostgreSQL `SET search_path` command familiar from PostgreSQL. This means that when you create migrations, you must define the same schema name in the connection URL that is used by the production database. For most of the users this is `dbo` (the default value). However, if the production database uses another schema name, all the migration SQL must be either edited by hand to reflect the production _or_ the connection URL must be changed before creating migrations (for example: `schema=name`). #### Cyclic references Circular references can occur between models when each model references another, creating a closed loop. When using a Microsoft SQL Server database, Prisma ORM will show a validation error if the [referential action](/orm/prisma-schema/data-model/relations/referential-actions) on a relation is set to something other than [`NoAction`](/orm/prisma-schema/data-model/relations/referential-actions#noaction). See [Special rules for referential actions in SQL Server](/orm/prisma-schema/data-model/relations/referential-actions/special-rules-for-referential-actions) for more information. #### Destructive changes Certain migrations will cause more changes than you might expect. For example: - Adding or removing `autoincrement()`. This cannot be achieved by modifying the column, but requires recreating the table (including all constraints, indices, and foreign keys) and moving all data between the tables. - Additionally, it is not possible to delete all the columns from a table (possible with PostgreSQL or MySQL). If a migration needs to recreate all table columns, it will also re-create the table. #### Shared default values are not supported In some cases, user might want to define default values as shared objects: ```sql file=default_objects.sql CREATE DEFAULT catcat AS 'musti'; CREATE TABLE cats ( id INT IDENTITY PRIMARY KEY, name NVARCHAR(1000) ); sp_bindefault 'catcat', 'dbo.cats.name'; ``` Using the stored procedure `sp_bindefault`, the default value `catcat` can be used in more than one table. The way Prisma ORM manages default values is per table: ```sql file=default_per_table.sql showLineNumbers CREATE TABLE cats ( id INT IDENTITY PRIMARY KEY, name NVARCHAR(1000) CONSTRAINT DF_cat_name DEFAULT 'musti' ); ``` The last example, when introspected, leads to the following model: ```prisma file=schema.prisma showLineNumbers model cats { id Int @id @default(autoincrement()) name String? @default("musti") } ``` And the first doesn't get the default value introspected: ```prisma file=schema.prisma showLineNumbers model cats { id Int @id @default(autoincrement()) name String? } ``` If using Prisma Migrate together with shared default objects, changes to them must be done manually to the SQL. ### Data model limitations #### Cannot use column with `UNIQUE` constraint and filtered index as foreign key Microsoft SQL Server [only allows one `NULL` value in a column that has a `UNIQUE` constraint](https://learn.microsoft.com/en-us/sql/relational-databases/tables/unique-constraints-and-check-constraints?view=sql-server-ver15). For example: - A table of users has a column named `license_number` - The `license_number` field has a `UNIQUE` constraint - The `license_number` field only allows **one** `NULL` value The standard way to get around this issue is to create a filtered unique index that excludes `NULL` values. This allows you to insert multiple `NULL` values. If you do not create an index in the database, you will get an error if you try to insert more than one `null` value into a column with Prisma Client. _However_, creating an index makes it impossible to use `license_number` as a foreign key in the database (or a relation scalar field in corresponding Prisma Schema) ### Raw query considerations #### Raw queries with `String @db.VarChar(n)` fields / `VARCHAR(N)` columns `String` query parameters in [raw queries](/orm/prisma-client/using-raw-sql/raw-queries) are always encoded to SQL Server as `NVARCHAR(4000)` (if your `String` length is \<= 4000) or `NVARCHAR(MAX)`. If you compare a `String` query parameter to a column of type `String @db.VarChar(N)`/`VARCHAR(N)`, this can lead to implicit conversion on SQL Server which affects your index performance and can lead to high CPU usage. Here is an example: ```prisma model user { id Int @id name String @db.VarChar(40) } ``` This query would be affected: ```ts await prisma.$queryRaw`SELECT * FROM user WHERE name = ${"John"}` ``` To avoid the problem, we recommend you always manually cast your `String` query parameters to `VARCHAR(N)` in the raw query: ```ts await prisma.$queryRaw`SELECT * FROM user WHERE name = CAST(${"John"} AS VARCHAR(40))` ``` This enables SQL Server to perform a Clustered Index Seek instead of a Clustered Index Scan. --- # CockroachDB URL: https://www.prisma.io/docs/orm/overview/databases/cockroachdb This guide discusses the concepts behind using Prisma ORM and CockroachDB, explains the commonalities and differences between CockroachDB and other database providers, and leads you through the process for configuring your application to integrate with CockroachDB. The CockroachDB connector is generally available in versions `3.14.0` and later. It was first added as a [Preview feature](/orm/reference/preview-features) in version [`3.9.0`](https://github.com/prisma/prisma/releases/tag/3.9.0) with support for Introspection, and Prisma Migrate support was added in [`3.11.0`](https://github.com/prisma/prisma/releases/tag/3.11.0). ## What is CockroachDB? CockroachDB is a distributed database that is designed for scalability and high availability. Features include: - **Compatibility with PostgreSQL:** CockroachDB is compatible with PostgreSQL, allowing interoperability with a large ecosystem of existing products - **Built-in scaling:** CockroachDB comes with automated replication, failover and repair capabilities to allow easy horizontal scaling of your application ## Commonalities with other database providers CockroachDB is largely compatible with PostgreSQL, and can mostly be used with Prisma ORM in the same way. You can still: - model your database with the [Prisma Schema Language](/orm/prisma-schema) - connect to your database, using Prisma ORM's [`cockroachdb` database connector](/orm/overview/databases/cockroachdb) - use [Introspection](/orm/prisma-schema/introspection) for existing projects if you already have a CockroachDB database - use [Prisma Migrate](/orm/prisma-migrate) to migrate your database schema to a new version - use [Prisma Client](/orm/prisma-client) in your application to query your database in a type safe way based on your Prisma Schema ## Differences to consider There are some CockroachDB-specific differences to be aware of when working with Prisma ORM's `cockroachdb` connector: - **Cockroach-specific native types:** Prisma ORM's `cockroachdb` database connector provides support for CockroachDB's native data types. To learn more, see [How to use CockroachDB's native types](#how-to-use-cockroachdbs-native-types). - **Creating database keys:** Prisma ORM allows you to generate a unique identifier for each record using the [`autoincrement()`](/orm/reference/prisma-schema-reference#autoincrement) function. For more information, see [How to use database keys with CockroachDB](#how-to-use-database-keys-with-cockroachdb). ## How to use Prisma ORM with CockroachDB This section provides more details on how to use CockroachDB-specific features. ### How to use CockroachDB's native types CockroachDB has its own set of native [data types](https://www.cockroachlabs.com/docs/stable/data-types.html) which are supported in Prisma ORM. For example, CockroachDB uses the `STRING` data type instead of PostgreSQL's `VARCHAR`. As a demonstration of this, say you create a `User` table in your CockroachDB database using the following SQL command: ```sql CREATE TABLE public."Post" ( "id" INT8 NOT NULL, "title" VARCHAR(200) NOT NULL, CONSTRAINT "Post_pkey" PRIMARY KEY ("id" ASC), FAMILY "primary" ("id", "title") ); ``` After introspecting your database with `npx prisma db pull`, you will have a new `Post` model in your Prisma Schema: ```prisma file=schema.prisma showLineNumbers model Post { id BigInt @id title String @db.String(200) } ``` Notice that the `title` field has been annotated with `@db.String(200)` — this differs from PostgreSQL where the annotation would be `@db.VarChar(200)`. For a full list of type mappings, see our [connector documentation](/orm/overview/databases/cockroachdb#type-mapping-between-cockroachdb-and-the-prisma-schema). ### How to use database keys with CockroachDB When generating unique identifiers for records in a distributed database like CockroachDB, it is best to avoid using sequential IDs – for more information on this, see CockroachDB's [blog post on choosing index keys](https://www.cockroachlabs.com/blog/how-to-choose-db-index-keys/). Instead, Prisma ORM provides the [`autoincrement()`](/orm/reference/prisma-schema-reference#autoincrement) attribute function, which uses CockroachDB's [`unique_rowid()` function](https://www.cockroachlabs.com/docs/stable/serial.html) for generating unique identifiers. For example, the following `User` model has an `id` primary key, generated using the `autoincrement()` function: ```prisma file=schema.prisma showLineNumbers model User { id BigInt @id @default(autoincrement()) name String } ``` For compatibility with existing databases, you may sometimes still need to generate a fixed sequence of integer key values. In these cases, you can use Prisma ORM's inbuilt [`sequence()`](/orm/reference/prisma-schema-reference#sequence) function for CockroachDB. For a list of available options for the `sequence()` function, see our [reference documentation](/orm/reference/prisma-schema-reference#sequence). For more information on generating database keys, see CockroachDB's [Primary key best practices](https://www.cockroachlabs.com/docs/v21.2/schema-design-table#primary-key-best-practices) guide. ## Example To connect to a CockroachDB database server, you need to configure a [`datasource`](/orm/prisma-schema/overview/data-sources) block in your [Prisma schema](/orm/prisma-schema): ```prisma file=schema.prisma showLineNumbers datasource db { provider = "cockroachdb" url = env("DATABASE_URL") } ``` The fields passed to the `datasource` block are: - `provider`: Specifies the `cockroachdb` data source connector. - `url`: Specifies the [connection URL](#connection-details) for the CockroachDB database server. In this case, an [environment variable is used](/orm/prisma-schema/overview#accessing-environment-variables-from-the-schema) to provide the connection URL. While `cockroachdb` and `postgresql` connectors are similar, it is mandatory to use the `cockroachdb` connector instead of `postgresql` when connecting to a CockroachDB database from version 5.0.0. ## Connection details CockroachDB uses the PostgreSQL format for its connection URL. See the [PostgreSQL connector documentation](/orm/overview/databases/postgresql#connection-details) for details of this format, and the optional arguments it takes. ## Differences between CockroachDB and PostgreSQL The following table lists differences between CockroachDB and PostgreSQL: | Issue | Area | Notes | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | By default, the `INT` type is an alias for `INT8` in CockroachDB, whereas in PostgreSQL it is an alias for `INT4`. This means that Prisma ORM will introspect an `INT` column in CockroachDB as `BigInt`, whereas in PostgreSQL Prisma ORM will introspect it as `Int`. | Schema | For more information on the `INT` type, see the [CockroachDB documentation](https://www.cockroachlabs.com/docs/stable/int.html#considerations-for-64-bit-signed-integers) | | When using `@default(autoincrement())` on a field, CockroachDB will automatically generate 64-bit integers for the row IDs. These integers will be increasing but not consecutive. This is in contrast to PostgreSQL, where generated row IDs are consecutive and start from 1. | Schema | For more information on generated values, see the [CockroachDB documentation](https://www.cockroachlabs.com/docs/stable/serial.html#generated-values-for-modes-rowid-and-virtual_sequence) | | The `@default(autoincrement())` attribute can only be used together with the `BigInt` field type. | Schema | For more information on generated values, see the [CockroachDB documentation](https://www.cockroachlabs.com/docs/stable/serial.html#generated-values-for-modes-rowid-and-virtual_sequence) | ## Type mapping limitations in CockroachDB The CockroachDB connector maps the [scalar types](/orm/prisma-schema/data-model/models#scalar-fields) from the Prisma ORM [data model](/orm/prisma-schema/data-model/models) to native column types. These native types are mostly the same as for PostgreSQL — see the [Native type mapping from Prisma ORM to CockroachDB](#native-type-mapping-from-prisma-orm-to-cockroachdb) for details. However, there are some limitations: | CockroachDB (Type \| Aliases) | Prisma ORM | Supported | Native database type attribute | Notes | | ----------------------------- | ---------- | :-------: | :----------------------------- | :------------------------------------------------------------------------------------------------------------------------- | | `money` | `Decimal` | Not yet | `@db.Money` | Supported in PostgreSQL but [not currently in CockroachDB](https://github.com/cockroachdb/cockroach/issues/41578) | | `xml` | `String` | Not yet | `@db.Xml` | Supported in PostgreSQL but [not currently in CockroachDB](https://github.com/cockroachdb/cockroach/issues/43355) | | `jsonb` arrays | `Json[]` | Not yet | N/A | `Json[]` supported in PostgreSQL but [not currently in CockroachDB](https://github.com/cockroachdb/cockroach/issues/23468) | ## Other limitations The following table lists any other current known limitations of CockroachDB compared to PostgreSQL: | Issue | Area | Notes | | ---------------------------------------------------------------------------------------------------- | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Index types `Hash`, `Gist`, `SpGist` or `Brin` are not supported. | Schema | In PostgreSQL, Prisma ORM allows [configuration of indexes](/orm/prisma-schema/data-model/indexes#configuring-the-access-type-of-indexes-with-type-postgresql) to use the different index access method. CockroachDB only currently supports `BTree` and `Gin`. | | Pushing to `Enum` types not supported | Client | Pushing to `Enum` types (e.g. `data: { enum { push: "A" }, }`) is currently [not supported in CockroachDB](https://github.com/cockroachdb/cockroach/issues/71388) | | Searching on `String` fields without a full text index not supported | Client | Searching on `String` fields without a full text index (e.g. `where: { text: { search: "cat & dog", }, },`) is currently [not supported in CockroachDB](https://github.com/cockroachdb/cockroach/issues/7821) | | Integer division not supported | Client | Integer division (e.g. `data: { int: { divide: 10, }, }`) is currently [not supported in CockroachDB](https://github.com/cockroachdb/cockroach/issues/41448) | | Limited filtering on `Json` fields | Client | Currently CockroachDB [only supports](https://github.com/cockroachdb/cockroach/issues/49144) `equals` and `not` filtering on `Json` fields | ## Type mapping between CockroachDB and the Prisma schema The CockroachDB connector maps the [scalar types](/orm/prisma-schema/data-model/models#scalar-fields) from the Prisma ORM [data model](/orm/prisma-schema/data-model/models) as follows to native column types: > Alternatively, see the [Prisma schema reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) for type mappings organized by Prisma ORM type. ### Native type mapping from Prisma ORM to CockroachDB | Prisma ORM | CockroachDB | | ---------- | ---------------- | | `String` | `STRING` | | `Boolean` | `BOOL` | | `Int` | `INT4` | | `BigInt` | `INT8` | | `Float` | `FLOAT8` | | `Decimal` | `DECIMAL(65,30)` | | `DateTime` | `TIMESTAMP(3)` | | `Json` | `JSONB` | | `Bytes` | `BYTES` | ### Mapping from CockroachDB to Prisma ORM types on Introspection When introspecting a CockroachDB database, the database types are mapped to Prisma ORM according to the following table: | CockroachDB (Type \| Aliases) | Prisma ORM | Supported | Native database type attribute | Notes | | -------------------------------------------- | ---------- | :-------: | :----------------------------- | :--------------------------------------------------------------------- | | `INT` \| `BIGINT`, `INTEGER` | `BigInt` | ✔️ | `@db.Int8` | | | `BOOL` \| `BOOLEAN` | `Bool` | ✔️ | `@db.Bool`\* | | | `TIMESTAMP` \| `TIMESTAMP WITHOUT TIME ZONE` | `DateTime` | ✔️ | `@db.Timestamp(x)` | | | `TIMESTAMPTZ` \| `TIMESTAMP WITH TIME ZONE` | `DateTime` | ✔️ | `@db.Timestamptz(x)` | | | `TIME` \| `TIME WITHOUT TIME ZONE` | `DateTime` | ✔️ | `@db.Time(x)` | | | `TIMETZ` \| `TIME WITH TIME ZONE` | `DateTime` | ✔️ | `@db.Timetz(x)` | | | `DECIMAL(p,s)` \| `NUMERIC(p,s)`, `DEC(p,s)` | `Decimal` | ✔️ | `@db.Decimal(x, y)` | | | `REAL` \| `FLOAT4`, `FLOAT` | `Float` | ✔️ | `@db.Float4` | | | `DOUBLE PRECISION` \| `FLOAT8` | `Float` | ✔️ | `@db.Float8` | | | `INT2` \| `SMALLINT` | `Int` | ✔️ | `@db.Int2` | | | `INT4` | `Int` | ✔️ | `@db.Int4` | | | `CHAR(n)` \| `CHARACTER(n)` | `String` | ✔️ | `@db.Char(x)` | | | `"char"` | `String` | ✔️ | `@db.CatalogSingleChar` | Internal type for CockroachDB catalog tables, not meant for end users. | | `STRING` \| `TEXT`, `VARCHAR` | `String` | ✔️ | `@db.String` | | | `DATE` | `DateTime` | ✔️ | `@db.Date` | | | `ENUM` | `enum` | ✔️ | N/A | | | `INET` | `String` | ✔️ | `@db.Inet` | | | `BIT(n)` | `String` | ✔️ | `@Bit(x)` | | | `VARBIT(n)` \| `BIT VARYING(n)` | `String` | ✔️ | `@VarBit` | | | `OID` | `Int` | ✔️ | `@db.Oid` | | | `UUID` | `String` | ✔️ | `@db.Uuid` | | | `JSONB` \| `JSON` | `Json` | ✔️ | `@db.JsonB` | | | Array types | `[]` | ✔️ | | | [Introspection](/orm/prisma-schema/introspection) adds native database types that are **not yet supported** as [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) fields: ```prisma file=schema.prisma showLineNumbers model Device { id BigInt @id @default(autoincrement()) interval Unsupported("INTERVAL") } ``` ## More on using CockroachDB with Prisma ORM The fastest way to start using CockroachDB with Prisma ORM is to refer to our Getting Started documentation: - [Start from scratch](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-cockroachdb) - [Add to existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-cockroachdb) These tutorials will take you through the process of connecting to CockroachDB, migrating your schema, and using Prisma Client. Further reference information is available in the [CockroachDB connector documentation](/orm/overview/databases/cockroachdb). --- # PlanetScale URL: https://www.prisma.io/docs/orm/overview/databases/planetscale Prisma and [PlanetScale](https://planetscale.com/) together provide a development arena that optimizes rapid, type-safe development of data access applications, using Prisma's ORM and PlanetScale's highly scalable MySQL-based platform. This document discusses the concepts behind using Prisma ORM and PlanetScale, explains the commonalities and differences between PlanetScale and other database providers, and leads you through the process for configuring your application to integrate with PlanetScale. ## What is PlanetScale? PlanetScale uses the [Vitess](https://vitess.io/) database clustering system to provide a MySQL-compatible database platform. Features include: - **Enterprise scalability.** PlanetScale provides a highly available production database cluster that supports scaling across multiple database servers. This is particularly useful in a serverless context, as it avoids the problem of having to [manage connection limits](/orm/prisma-client/setup-and-configuration/databases-connections#serverless-environments-faas). - **Database branches.** PlanetScale allows you to create [branches of your database schema](https://planetscale.com/docs/concepts/branching), so that you can test changes on a development branch before applying them to your production database. - **Support for [non-blocking schema changes](https://planetscale.com/docs/concepts/nonblocking-schema-changes).** PlanetScale provides a workflow that allows users to update database schemas without locking the database or causing downtime. ## Commonalities with other database providers Many aspects of using Prisma ORM with PlanetScale are just like using Prisma ORM with any other relational database. You can still: - model your database with the [Prisma Schema Language](/orm/prisma-schema) - use Prisma ORM's existing [`mysql` database connector](/orm/overview/databases/mysql) in your schema, along with the [connection string PlanetScale provides you](https://planetscale.com/docs/concepts/connection-strings) - use [Introspection](/orm/prisma-schema/introspection) for existing projects if you already have a database schema in PlanetScale - use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) to push changes in your schema to the database - use [Prisma Client](/orm/prisma-client) in your application to talk to the database server at PlanetScale ## Differences to consider PlanetScale's branching model and design for scalability means that there are also a number of differences to consider. You should be aware of the following points when deciding to use PlanetScale with Prisma ORM: - **Branching and deploy requests.** PlanetScale provides two types of database branches: _development branches_, which allow you to test out schema changes, and _production branches_, which are protected from direct schema changes. Instead, changes must be first created on a development branch and then deployed to production using a deploy request. Production branches are highly available and include automated daily backups. To learn more, see [How to use branches and deploy requests](#how-to-use-branches-and-deploy-requests). - **Referential actions and integrity.** To support scaling across multiple database servers, PlanetScale [by default does not use foreign key constraints](https://planetscale.com/docs/learn/operating-without-foreign-key-constraints), which are normally used in relational databases to enforce relationships between data in different tables, and asks users to handle this manually in their applications. However, you can explicitly [enable them in the PlanetScale database settings](https://planetscale.com/docs/concepts/foreign-key-constraints). If you don't enable these explicitly, you can still maintain these relationships in your data and allow the use of [referential actions](/orm/prisma-schema/data-model/relations/referential-actions) by using Prisma ORM's ability to [emulate relations in Prisma Client](/orm/prisma-schema/data-model/relations/relation-mode#emulate-relations-in-prisma-orm-with-the-prisma-relation-mode) with the `prisma` relation mode. For more information, see [How to emulate relations in Prisma Client](#option-1-emulate-relations-in-prisma-client). - **Creating indexes on foreign keys.** When [emulating relations in Prisma ORM](#option-1-emulate-relations-in-prisma-client) (i.e. when _not_ using foreign key constraints on the database-level), you will need to create dedicated indexes on foreign keys. In a standard MySQL database, if a table has a column with a foreign key constraint, an index is automatically created on that column. When PlanetScale is configured to not use foreign key constraints, these indexes are [currently](https://github.com/prisma/prisma/issues/10611) not created when Prisma Client emulates relations, which can lead to issues with queries not being well optimized. To avoid this, you can create indexes in Prisma ORM. For more information, see [How to create indexes on foreign keys](#2-create-indexes-on-foreign-keys). - **Making schema changes with `db push`.** When you merge a development branch into your production branch, PlanetScale will automatically compare the two schemas and generate its own schema diff. This means that Prisma ORM's [`prisma migrate`](/orm/prisma-migrate) workflow, which generates its own history of migration files, is not a natural fit when working with PlanetScale. These migration files may not reflect the actual schema changes run by PlanetScale when the branch is merged. We recommend not using `prisma migrate` when making schema changes with PlanetScale. Instead, we recommend that you use the `prisma db push` command. For an example of how this works, see [How to make schema changes with `db push`](#how-to-make-schema-changes-with-db-push) - **Introspection**. When you introspect on an existing database and you have _not_ enabled [foreign key constraints in your PlanetScale database](#option-2-enable-foreign-key-constraints-in-the-planetscale-database-settings), you will get a schema with no relations, as they are usually defined based on foreign keys that connect tables. In that case, you will need to add the missing relations in manually. For more information, see [How to add in missing relations after Introspection](#how-to-add-in-missing-relations-after-introspection). ## How to use branches and deploy requests When connecting to PlanetScale with Prisma ORM, you will need to use the correct connection string for your branch. The connection URL for a given database branch can be found from your PlanetScale account by going to the overview page for the branch and selecting the 'Connect' dropdown. In the 'Passwords' section, generate a new password and select 'Prisma' from the dropdown to get the Prisma format for the connection URL. See Prisma ORM's [Getting Started guide](/getting-started/setup-prisma/start-from-scratch/relational-databases/connect-your-database-typescript-planetscale) for more details of how to connect to a PlanetScale database. Every PlanetScale database is created with a branch called `main`, which is initially a development branch that you can use to test schema changes on. Once you are happy with the changes you make there, you can [promote it](https://planetscale.com/docs/concepts/branching#promote-a-branch-to-production) to become a production branch. Note that you can only push new changes to a development branch, so further changes will need to be created on a separate development branch and then later deployed to production using a [deploy request](https://planetscale.com/docs/concepts/branching#promote-a-branch-to-production). If you try to push to a production branch, you will get the [error message](/orm/reference/error-reference#p3022) `Direct execution of DDL (Data Definition Language) SQL statements is disabled on this database.` ## How to use relations (and enable referential integrity) with PlanetScale ### Option 1: Emulate relations in Prisma Client #### 1. Set `relationMode = "prisma"` PlanetScale does not use foreign key constraints in its database schema by default. However, Prisma ORM relies on foreign key constraints in the underlying database to enforce referential integrity between models in your Prisma schema. In Prisma ORM versions 3.1.1 and later, you can [emulate relations in Prisma Client with the `prisma` relation mode](/orm/prisma-schema/data-model/relations/relation-mode#emulate-relations-in-prisma-orm-with-the-prisma-relation-mode), which avoids the need for foreign key constraints in the database. To enable emulation of relations in Prisma Client, set the `relationMode` field to `"prisma"` in the `datasource` block: ```prisma file=schema.prisma showLineNumbers datasource db { provider = "mysql" url = env("DATABASE_URL") relationMode = "prisma" } ``` The ability to set the relation mode was introduced as part of the `referentialIntegrity` preview feature in Prisma ORM version 3.1.1, and is generally available in Prisma ORM versions 4.8.0 and later.

The `relationMode` field was renamed in Prisma ORM version 4.5.0, and was previously named `referentialIntegrity`.
If you use relations in your Prisma schema with the default `"foreignKeys"` option for the `relationMode` field, PlanetScale will error and Prisma ORM output the [P3021 error message](/orm/reference/error-reference#p3021) when it tries to create foreign keys. (In versions before 2.27.0 it will output a raw database error.) #### 2. Create indexes on foreign keys When [you emulate relations in Prisma Client](#option-1-emulate-relations-in-prisma-client), you need to create your own indexes. As an example of a situation where you would want to add an index, take this schema for a blog with posts and comments: ```prisma file=schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) title String content String likes Int @default(0) comments Comment[] } model Comment { id Int @id @default(autoincrement()) comment String postId Int post Post @relation(fields: [postId], references: [id], onDelete: Cascade) } ``` The `postId` field in the `Comment` model refers to the corresponding `id` field in the `Post` model. However this is not implemented as a foreign key in PlanetScale, so the column doesn't have an automatic index. This means that some queries may not be well optimized. For example, if you query for all comments with a certain post `id`, PlanetScale may have to do a full table lookup. This could be slow, and also expensive because PlanetScale's billing model charges for the number of rows read. To avoid this, you can define an index on the `postId` field using [Prisma ORM's `@@index` argument](/orm/reference/prisma-schema-reference#index): ```prisma file=schema.prisma highlight=15;add showLineNumbers model Post { id Int @id @default(autoincrement()) title String content String likes Int @default(0) comments Comment[] } model Comment { id Int @id @default(autoincrement()) comment String postId Int post Post @relation(fields: [postId], references: [id], onDelete: Cascade) //add-next-line @@index([postId]) } ``` You can then add this change to your schema [using `db push`](#how-to-make-schema-changes-with-db-push). In versions 4.7.0 and later, Prisma ORM warns you if you have a relation with no index on the relation scalar field. For more information, see [Index validation](/orm/prisma-schema/data-model/relations/relation-mode#index-validation). One issue to be aware of is that [implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations) cannot have an index added in this way. If query speed or cost is an issue, you may instead want to use an [explicit many-to-many relation](/orm/prisma-schema/data-model/relations/many-to-many-relations#explicit-many-to-many-relations) in this case. ### Option 2: Enable foreign key constraints in the PlanetScale database settings Support for foreign key constraints in PlanetScale databases has been Generally Available since February 2024. Follow the instructions in the [PlanetScale documentation](https://planetscale.com/docs/concepts/foreign-key-constraints) to enable them in your database. You can then use Prisma ORM and define relations in your Prisma schema without the need for extra configuration. In that case, you can define a relation as with other database that supports foreign key constraints, for example: ```prisma file=schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) title String content String likes Int @default(0) comments Comment[] } model Comment { id Int @id @default(autoincrement()) comment String postId Int post Post @relation(fields: [postId], references: [id], onDelete: Cascade) } ``` With this approach, it is _not_ necessary to: - set `relationMode = "prisma"` in your Prisma schema - define additional indexes on foreign keys Also, introspection will automatically create relation fields in your Prisma schema because it can detect the foreign key constraints in the database. ## How to make schema changes with `db push` To use `db push` with PlanetScale, you will first need to [enable emulation of relations in Prisma Client](#option-1-emulate-relations-in-prisma-client). Pushing to your branch without referential emulation enabled will give the [error message](/orm/reference/error-reference#p3021) `Foreign keys cannot be created on this database.` As an example, let's say you decide to decide to add a new `excerpt` field to the blog post schema above. You will first need to [create a new development branch and connect to it](#how-to-use-branches-and-deploy-requests). Next, add the following to your `schema.prisma` file: ```prisma file=schema.prisma highlight=5;edit showLineNumbers model Post { id Int @id @default(autoincrement()) title String content String //edit-next-line excerpt String? likes Int @default(0) comments Comment[] } model Comment { id Int @id @default(autoincrement()) comment String postId Int post Post @relation(fields: [postId], references: [id], onDelete: Cascade) @@index([postId]) } ``` To push these changes, navigate to your project directory in your terminal and run ```terminal npx prisma db push ``` Once you are happy with your changes on your development branch, you can open a deploy request to deploy these to your production branch. For more examples, see PlanetScale's tutorial on [automatic migrations with Prisma ORM](https://planetscale.com/docs/prisma/automatic-prisma-migrations) using `db push`. ## How to add in missing relations after Introspection > **Note**: This section is only relevant if you use `relationMode = "prisma"` to emulate foreign key constraints with Prisma ORM. If you enabled foreign key constraints in your PlanetScale database, you can ignore this section. After introspecting with `npx prisma db pull`, the schema you get may be missing some relations. For example, the following schema is missing a relation between the `User` and `Post` models: ```prisma file=schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) title String @db.VarChar(255) content String? authorId Int @@index([authorId]) } model User { id Int @id @default(autoincrement()) email String @unique name String? } ``` In this case you need to add the relation in manually: ```prisma file=schema.prisma highlight=6,16;add showLineNumbers model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) title String @db.VarChar(255) content String? //add-next-line author User @relation(fields: [authorId], references: [id]) authorId Int @@index([authorId]) } model User { id Int @id @default(autoincrement()) email String @unique name String? //add-next-line posts Post[] } ``` For a more detailed example, see the [Getting Started guide for PlanetScale](/getting-started/setup-prisma/add-to-existing-project/relational-databases/introspection-typescript-planetscale). ## How to use the PlanetScale serverless driver with Prisma ORM (Preview) The [PlanetScale serverless driver](https://planetscale.com/docs/tutorials/planetscale-serverless-driver) provides a way of communicating with your database and executing queries over HTTP. You can use Prisma ORM along with the PlanetScale serverless driver using the [`@prisma/adapter-planetscale`](https://www.npmjs.com/package/@prisma/adapter-planetscale) driver adapter. The driver adapter allows you to communicate with your database over HTTP. :::info This feature is available in Preview from Prisma ORM versions 5.4.2 and later. ::: To get started, enable the `driverAdapters` Preview feature flag: ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["driverAdapters"] } ``` Generate Prisma Client: ```bash npx prisma generate ``` :::info Ensure you update the host value in your connection string to `aws.connect.psdb.cloud`. You can learn more about this [here](https://planetscale.com/docs/tutorials/planetscale-serverless-driver#add-and-use-the-planetscale-serverless-driver-for-javascript-to-your-project). ```bash DATABASE_URL='mysql://johndoe:strongpassword@aws.connect.psdb.cloud/clear_nightsky?sslaccept=strict' ``` ::: Install the Prisma ORM adapter for PlanetScale, PlanetScale serverless driver and `undici` packages: ```bash npm install @prisma/adapter-planetscale undici ``` :::info When using a Node.js version below 18, you must provide a custom fetch function implementation. We recommend the `undici` package on which Node's built-in fetch is based. Node.js versions 18 and later include a built-in global `fetch` function, so you don't have to install an extra package. ::: Update your Prisma Client instance to use the PlanetScale serverless driver: ```ts import { PrismaPlanetScale } from '@prisma/adapter-planetscale' import { PrismaClient } from '@prisma/client' import dotenv from 'dotenv' import { fetch as undiciFetch } from 'undici' dotenv.config() const connectionString = `${process.env.DATABASE_URL}` const adapter = new PrismaPlanetScale({ url: connectionString, fetch: undiciFetch }) const prisma = new PrismaClient({ adapter }) ``` You can then use Prisma Client as you normally would with full type-safety. Prisma Migrate, introspection, and Prisma Studio will continue working as before using the connection string defined in the Prisma schema. ## More on using PlanetScale with Prisma ORM The fastest way to start using PlanetScale with Prisma ORM is to refer to our Getting Started documentation: - [Start from scratch](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-planetscale) - [Add to existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-planetscale) These tutorials will take you through the process of connecting to PlanetScale, pushing schema changes, and using Prisma Client. For further tips on best practices when using Prisma ORM and PlanetScale together, watch our video:
--- # Supabase URL: https://www.prisma.io/docs/orm/overview/databases/supabase This guide discusses the concepts behind using Prisma ORM and Supabase, explains the commonalities and differences between Supabase and other database providers, and leads you through the process for configuring your application to integrate with Supabase. ## What is Supabase? [Supabase](https://supabase.com/) is a PostgreSQL hosting service and open source Firebase alternative providing all the backend features you need to build a product. Unlike Firebase, Supabase is backed by PostgreSQL which can be accessed directly using Prisma ORM. To learn more about Supabase, you can check out their architecture [here](https://supabase.com/docs/guides/getting-started/architecture) and features [here](https://supabase.com/docs/guides/getting-started/features) ## Commonalities with other database providers Many aspects of using Prisma ORM with Supabase are just like using Prisma ORM with any other relational database. You can still: - model your database with the [Prisma Schema Language](/orm/prisma-schema) - use Prisma ORM's existing [`postgresql` database connector](/orm/overview/databases/postgresql) in your schema, along with the [connection string Supabase provides you](https://supabase.com/docs/guides/database/connecting-to-postgres#connecting-to-external-libraries-and-tools) - use [Introspection](/orm/prisma-schema/introspection) for existing projects if you already have a database schema in Supabase - use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) to push changes in your schema to Supabase - use [Prisma Client](/orm/prisma-client) in your application to talk to the database server at Supabase ## Specific considerations If you'd like to use the [connection pooling feature](https://supabase.com/docs/guides/database/connecting-to-postgres#connection-pooling-in-depth) available with Supabase, you will need to use the connection pooling connection string available via your [Supabase database settings](https://supabase.com/dashboard/project/_/settings/database) with `?pgbouncer=true` appended to the end of your `DATABASE_URL` environment variable: ```env file=.env # Connect to Supabase via connection pooling with Supavisor. DATABASE_URL="postgres://postgres.[your-supabase-project]:[password]@aws-0-[aws-region].pooler.supabase.com:6543/postgres?pgbouncer=true" ``` If you would like to use the Prisma CLI in order to perform other actions on your database (e.g. migrations) you will need to add a `DIRECT_URL` environment variable to use in the `datasource.directUrl` property so that the CLI can bypass Supavisor: ```env file=.env highlight=4-5;add showLineNumbers # Connect to Supabase via connection pooling with Supavisor. DATABASE_URL="postgres://postgres.[your-supabase-project]:[password]@aws-0-[aws-region].pooler.supabase.com:6543/postgres?pgbouncer=true" //add-start # Direct connection to the database. Used for migrations. DIRECT_URL="postgres://postgres.[your-supabase-project]:[password]@aws-0-[aws-region].pooler.supabase.com:5432/postgres" //add-end ``` You can then update your `schema.prisma` to use the new direct URL: ```prisma file=schema.prisma highlight=4;add showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") //add-next-line directUrl = env("DIRECT_URL") } ``` More information about the `directUrl` field can be found [here](/orm/reference/prisma-schema-reference#fields). We strongly recommend using connection pooling with Supavisor in addition to `DIRECT_URL`. You will gain the great developer experience of the Prisma CLI while also allowing for connections to be pooled regardless of your deployment strategy. While this is not strictly necessary for every app, serverless solutions will inevitably require connection pooling. ## Getting started with Supabase If you're interested in learning more, Supabase has a great guide for connecting a database provided by Supabase to your Prisma project available [here](https://supabase.com/partners/integrations/prisma). If you're running into issues integrating with Supabase, check out these [specific troubleshooting tips](https://supabase.com/partners/integrations/prisma) or [Prisma's GitHub Discussions](https://github.com/prisma/prisma/discussions) for more help. --- # Neon URL: https://www.prisma.io/docs/orm/overview/databases/neon This guide explains how to: - [Connect Prisma ORM using Neon's connection pooling feature](#how-to-use-neons-connection-pooling) - [Resolve connection timeout issues](#resolving-connection-timeouts) - [Use Neon's serverless driver with Prisma ORM](#how-to-use-neons-serverless-driver-with-prisma-orm-preview) ## What is Neon? [Neon](https://neon.tech/) is a fully managed serverless PostgreSQL with a generous free tier. Neon separates storage and compute, and offers modern developer features such as serverless, branching, bottomless storage, and more. Neon is open source and written in Rust. Learn more about Neon [here](https://neon.tech/docs/introduction). ## Commonalities with other database providers Many aspects of using Prisma ORM with Neon are just like using Prisma ORM with any other PostgreSQL database. You can: - model your database with the [Prisma Schema Language](/orm/prisma-schema) - use Prisma ORM's [`postgresql` database connector](/orm/overview/databases/postgresql) in your schema, along with the [connection string Neon provides you](https://neon.tech/docs/connect/connect-from-any-app) - use [Introspection](/orm/prisma-schema/introspection) for existing projects if you already have a database schema on Neon - use [`prisma migrate dev`](/orm/prisma-migrate/workflows/development-and-production) to track schema migrations in your Neon database - use [`prisma db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) to push changes in your schema to Neon - use [Prisma Client](/orm/prisma-client) in your application to communicate with the database hosted by Neon ## Differences to consider There are a few differences between Neon and PostgreSQL you should be aware of the following when deciding to use Neon with Prisma ORM: - **Neon's serverless model** — By default, Neon scales a [compute](https://neon.tech/docs/introduction/compute-lifecycle) to zero after 5 minutes of inactivity. During this state, a compute instance is in _idle_ state. A characteristic of this feature is the concept of a "cold start". Activating a compute from an idle state takes from 500ms to a few seconds. Depending on how long it takes to connect to your database, your application may timeout. To learn more, see: [Connection latency and timeouts](https://neon.tech/docs/guides/prisma#connection-timeouts). - **Neon's connection pooler** — Neon offers connection pooling using PgBouncer, enabling up to 10,000 concurrent connections. To learn more, see: [Connection pooling](https://neon.tech/docs/connect/connection-pooling). ## How to use Neon's connection pooling If you would like to use the [connection pooling](https://neon.tech/docs/guides/prisma#use-connection-pooling-with-prisma) available in Neon, you will need to add `-pooler` in the hostname of your `DATABASE_URL` environment variable used in the `url` property of the `datasource` block of your Prisma schema: ```bash file=.env # Connect to Neon with Pooling. DATABASE_URL=postgres://daniel:@ep-mute-rain-952417-pooler.us-east-2.aws.neon.tech:5432/neondb?sslmode=require ``` If you would like to use Prisma CLI in order to perform other actions on your database (e.g. for migrations) you will need to add a `DIRECT_URL` environment variable to use in the `directUrl` property of the `datasource` block of your Prisma schema so that the CLI will use a direct connection string (without PgBouncer): ```env file=.env highlight=4-5;add showLineNumbers # Connect to Neon with Pooling. DATABASE_URL=postgres://daniel:@ep-mute-rain-952417-pooler.us-east-2.aws.neon.tech/neondb?sslmode=require //add-start # Direct connection to the database used by Prisma CLI for e.g. migrations. DIRECT_URL="postgres://daniel:@ep-mute-rain-952417.us-east-2.aws.neon.tech/neondb" //add-end ``` You can then update your `schema.prisma` to use the new direct URL: ```prisma file=schema.prisma highlight=4;add showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") //add-next-line directUrl = env("DIRECT_URL") } ``` More information about the `directUrl` field can be found [here](/orm/reference/prisma-schema-reference#fields). We strongly recommend using the pooled connection string in your `DATABASE_URL` environment variable. You will gain the great developer experience of the Prisma CLI while also allowing for connections to be pooled regardless of deployment strategy. While this is not strictly necessary for every app, serverless solutions will inevitably require connection pooling. ## Resolving connection timeouts A connection timeout that occurs when connecting from Prisma ORM to Neon causes an error similar to the following: ```text no-copy Error: P1001: Can't reach database server at `ep-white-thunder-826300.us-east-2.aws.neon.tech`:`5432` Please make sure your database server is running at `ep-white-thunder-826300.us-east-2.aws.neon.tech`:`5432`. ``` This error most likely means that the connection created by Prisma Client timed out before the Neon compute was activated. A Neon compute has two main states: _Active_ and _Idle_. Active means that the compute is currently running. If there is no query activity for 5 minutes, Neon places a compute into an idle state by default. Refer to Neon's docs to [learn more](https://neon.tech/docs/introduction/compute-lifecycle). When you connect to an idle compute from Prisma ORM, Neon automatically activates it. Activation typically happens within a few seconds but added latency can result in a connection timeout. To address this issue, your can adjust your Neon connection string by adding a `connect_timeout` parameter. This parameter defines the maximum number of seconds to wait for a new connection to be opened. The default value is 5 seconds. A higher setting should provide the time required to avoid connection timeout issues. For example: ```text wrap DATABASE_URL=postgres://daniel:@ep-mute-rain-952417.us-east-2.aws.neon.tech/neondb?connect_timeout=10 ``` :::info A `connect_timeout` setting of 0 means no timeout. ::: Another possible cause of connection timeouts is Prisma ORM's [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool), which has a default timeout of 10 seconds. This is typically enough time for Neon, but if you are still experiencing connection timeouts, you can try increasing this limit (in addition to the `connect_timeout` setting described above) by setting the `pool_timeout` parameter to a higher value. For example: ```text wrap DATABASE_URL=postgres://daniel:@ep-mute-rain-952417.us-east-2.aws.neon.tech/neondb?connect_timeout=15&pool_timeout=15 ``` ## How to use Neon's serverless driver with Prisma ORM (Preview) The [Neon serverless driver](https://github.com/neondatabase/serverless) is a low-latency Postgres driver for JavaScript and TypeScript that allows you to query data from serverless and edge environments over HTTP or WebSockets in place of TCP. You can use Prisma ORM along with the Neon serverless driver using a [driver adapter](/orm/overview/databases/database-drivers#driver-adapters) . A driver adapter allows you to use a different database driver from the default Prisma ORM provides to communicate with your database. :::info This feature is available in Preview from Prisma ORM versions 5.4.2 and later. ::: To get started, enable the `driverAdapters` Preview feature flag: ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["driverAdapters"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` Generate Prisma Client: ```terminal npx prisma generate ``` Install the Prisma ORM adapter for Neon: ```terminal npm install @prisma/adapter-neon ``` Update your Prisma Client instance: ```ts import { PrismaClient } from '@prisma/client' import { PrismaNeon } from '@prisma/adapter-neon' import dotenv from 'dotenv' dotenv.config() const connectionString = `${process.env.DATABASE_URL}` const adapter = new PrismaNeon({ connectionString }) const prisma = new PrismaClient({ adapter }) ``` You can then use Prisma Client as you normally would with full type-safety. Prisma Migrate, introspection, and Prisma Studio will continue working as before, using the connection string defined in the Prisma schema. ### Notes #### Specifying a PostgreSQL schema You can specify a [PostgreSQL schema](https://www.postgresql.org/docs/current/ddl-schemas.html) by passing in the `schema` option when instantiating `PrismaNeon`: ```ts const adapter = new PrismaNeon( { connectionString }, { schema: 'myPostgresSchema' }) ``` --- # Turso URL: https://www.prisma.io/docs/orm/overview/databases/turso This guide discusses the concepts behind using Prisma ORM and Turso, explains the commonalities and differences between Turso and other database providers, and leads you through the process for configuring your application to integrate with Turso. Prisma ORM support for Turso is currently in [Early Access](/orm/more/releases#early-access). We would appreciate your feedback in this [GitHub discussion](https://github.com/prisma/prisma/discussions/21345). ## What is Turso? [Turso](https://turso.tech/) is an edge-hosted, distributed database that's based on [libSQL](https://turso.tech/libsql), an open-source and open-contribution fork of [SQLite](https://sqlite.org/), enabling you to bring data closer to your application and minimize query latency. Turso can also be hosted on a remote server. :::warning Support for Turso is available in [Early Access](/orm/more/releases#early-access) from Prisma ORM versions 5.4.2 and later. ::: ## Commonalities with other database providers libSQL is 100% compatible with SQLite. libSQL extends SQLite and adds the following features and capabilities: - Support for replication - Support for automated backups - Ability to embed Turso as part of other programs such as the Linux kernel - Supports user-defined functions - Support for asynchronous I/O > To learn more about the differences between libSQL and how it is different from SQLite, see [libSQL Manifesto](https://turso.tech/libsql-manifesto). Many aspects of using Prisma ORM with Turso are just like using Prisma ORM with any other relational database. You can still: - model your database with the [Prisma Schema Language](/orm/prisma-schema) - use Prisma ORM's existing [`sqlite` database connector](/orm/overview/databases/sqlite) in your schema - use [Prisma Client](/orm/prisma-client) in your application to talk to the database server at Turso ## Differences to consider There are a number of differences between Turso and SQLite to consider. You should be aware of the following when deciding to use Turso and Prisma ORM: - **Remote and embedded SQLite databases**. libSQL uses HTTP to connect to the remote SQLite database. libSQL also supports remote database replicas and embedded replicas. Embedded replicas enable you to replicate your primary database inside your application. - **Making schema changes**. Since libSQL uses HTTP to connect to the remote database, this makes it incompatible with Prisma Migrate. However, you can use [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) to create a schema migration and then apply the changes to your database using [Turso's CLI](https://docs.turso.tech/reference/turso-cli). ## How to connect and query a Turso database The subsequent section covers how you can create a Turso database, retrieve your database credentials and connect to your database. ### How to provision a database and retrieve database credentials :::info Ensure that you have the [Turso CLI](https://docs.turso.tech/reference/turso-cli) installed to manage your databases. ::: If you don't have an existing database, you can provision a database by running the following command: ```terminal turso db create turso-prisma-db ``` The above command will create a database in the closest region to your location. Run the following command to retrieve your database's connection string: ```terminal turso db show turso-prisma-db ``` Next, create an authentication token that will allow you to connect to the database: ```terminal turso db tokens create turso-prisma-db ``` Update your `.env` file with the authentication token and connection string: ```bash file=.env TURSO_AUTH_TOKEN="eyJhbGciOiJFZERTQSIsInR5cCI6IkpXVCJ9..." TURSO_DATABASE_URL="libsql://turso-prisma-db-user.turso.io" ``` ### How to connect to a Turso database To get started, enable the `driverAdapters` Preview feature flag: ```prisma highlight=3;add generator client { provider = "prisma-client-js" //add-next-line previewFeatures = ["driverAdapters"] } datasource db { provider = "sqlite" url = "file:./dev.db" // will be ignored } ``` Generate Prisma Client: ```terminal npx prisma generate ``` Install the Prisma ORM driver adapter for libSQL packages: ```terminal npm install @prisma/adapter-libsql ``` Update your Prisma Client instance: ```ts import { PrismaClient } from '@prisma/client' import { PrismaLibSQL } from '@prisma/adapter-libsql' const adapter = new PrismaLibSQL({ url: `${process.env.TURSO_DATABASE_URL}`, authToken: `${process.env.TURSO_AUTH_TOKEN}`, }) const prisma = new PrismaClient({ adapter }) ``` You can use Prisma Client as you normally would with full type-safety in your project. ## Using Prisma Migrate via a driver adapter in `prisma.config.ts` (Early Access) As of [v6.6.0](https://pris.ly/release/6.6.0) and with a `prisma.config.ts` file, you can use `prisma db push` to make changes to your database schema. :::warning This functionality has been introduced in [Early Access](/orm/more/releases#early-access) in [v6.6.0](https://pris.ly/release/6.6.0) and supports the following commands: - `prisma db push` - `prisma db pull` - `prisma migrate diff` Other commands like `prisma migrate dev` and `prisma migrate deploy` will be added soon. ::: ### 1. Install the LibSQL driver adapter Run this command in your terminal: ```termina npm install @prisma/adapter-libsql ``` ### 2. Set environment variables In order to set up the LibSQL adapter, you'll need to add a few secrets to a `.env` file: - `LIBSQL_DATABASE_URL`: The connection URL of your Turso database instance. - `LIBSQL_DATABASE_TOKEN`: The token of your Turso database instance. You can then add these to your `.env` file or use them directly if they are stored in a different secret store: ```bash file=.env LIBSQL_DATABASE_URL="..." LIBSQL_DATABASE_TOKEN="..." ``` ### 3. Set up Prisma Config file Make sure that you have a [`prisma.config.ts`](/orm/reference/prisma-config-reference) file for your project. Then, set up the [migration driver adapter](/orm/reference/prisma-config-reference#migrateadapter) to use `PrismaLibSQL`: ```ts file=prisma.config.ts import path from 'node:path' import { defineConfig } from 'prisma/config' import { PrismaLibSQL } from '@prisma/adapter-libsql' // import your .env file import 'dotenv/config' type Env = { LIBSQL_DATABASE_URL: string LIBSQL_DATABASE_TOKEN: string } export default defineConfig({ earlyAccess: true, schema: path.join('prisma', 'schema.prisma'), migrate: { async adapter(env) { return new PrismaLibSQL({ url: env.LIBSQL_DATABASE_URL, authToken: env.LIBSQL_DATABASE_TOKEN, }) } } }) ``` ### 4. Migrate your database Prisma Migrate now will run migrations against your remote Turso database based on the configuration provided in `prisma.config.ts`. To create your first migration with this workflow, run the following command: ```terminal npx prisma db push ``` ## Embedded Turso database replicas Turso supports [embedded replicas](https://turso.tech/blog/introducing-embedded-replicas-deploy-turso-anywhere-2085aa0dc242). Turso's embedded replicas enable you to have a copy of your primary, remote database _inside_ your application. Embedded replicas behave similarly to a local SQLite database. Database queries are faster because your database is inside your application. ### How embedded database replicas work When your app initially establishes a connection to your database, the primary database will fulfill the query: ![Embedded Replica: First remote read](./images/embedded-replica-remote-read.png) Turso will (1) create an embedded replica inside your application and (2) copy data from your primary database to the replica so it is locally available: ![Embedded Replica: Remote DB Copy](./images/embedded-replica-create-replica.png) The embedded replica will fulfill subsequent read queries. The libSQL client provides a [`sync()`](https://docs.turso.tech/sdk/ts/reference#manual-sync) method which you can invoke to ensure the embedded replica's data remains fresh. ![Embedded Replica: Local DB reads](./images/embedded-replica-read.png) With embedded replicas, this setup guarantees a responsive application, because the data will be readily available locally and faster to access. Like a read replica setup you may be familiar with, write operations are forwarded to the primary remote database and executed before being propagated to all embedded replicas. ![Embedded Replica: Write operation propagation](./images/embedded-replica-write-propagation.png) 1. Write operations propagation are forwarded to the database. 1. Database responds to the server with the updates from 1. 1. Write operations are propagated to the database replica. Your application's data needs will determine how often you should synchronize data between your remote database and embedded database replica. For example, you can use either middleware functions (e.g. Express and Fastify) or a cron job to synchronize the data. ### How to synchronize data between your remote database and embedded replica To get started using embedded replicas with Prisma ORM, add the `sync()` method from libSQL in your application. The example below shows how you can synchronize data using Express middleware. ```ts highlight=5-8;add; import express from 'express' const app = express() // ... the rest of your application code //add-start app.use(async (req, res, next) => { await libsql.sync() next() }) //add-end app.listen(3000, () => console.log(`Server ready at http://localhost:3000`)) ``` It could be also implemented as a [Prisma Client extension](/orm/prisma-client/client-extensions). The below example shows auto-syncing after create, update or delete operation is performed. ```ts highlight=5-8 const prisma = new PrismaClient().$extends({ query: { $allModels: { async $allOperations({ operation, model, args, query }) { const result = await query(args) // Synchronize the embedded replica after any write operation if (['create', 'update', 'delete'].includes(operation)) { await libsql.sync() } return result } } } }) ``` --- # Cloudflare D1 URL: https://www.prisma.io/docs/orm/overview/databases/cloudflare-d1 This page discusses the concepts behind using Prisma ORM and Cloudflare D1, explains the commonalities and differences between Cloudflare D1 and other database providers, and leads you through the process for configuring your application to integrate with Cloudflare D1. Prisma ORM support for Cloudflare D1 is currently in [Preview](/orm/more/releases#preview). We would appreciate your feedback [on GitHub](https://github.com/prisma/prisma/discussions/23646). If you want to deploy a Cloudflare Worker with D1 and Prisma ORM, follow this [tutorial](/guides/cloudflare-d1). ## What is Cloudflare D1? D1 is Cloudflare's native serverless database and was initially [launched in 2022](https://blog.cloudflare.com/introducing-d1/). It's based on SQLite and can be used when deploying applications with Cloudflare Workers. Following Cloudflare's principles of geographic distribution and bringing compute and data closer to application users, D1 supports automatic read-replication. It dynamically manages the number of database instances and locations of read-only replicas based on how many queries a database is getting, and from where. For write-operations, queries travel to a single primary instance in order to propagate the changes to all read-replicas and ensure data consistency. ## Commonalities with other database providers D1 is based on SQLite. Many aspects of using Prisma ORM with D1 are just like using Prisma ORM with any other relational database. You can still: - model your database with the [Prisma Schema Language](/orm/prisma-schema) - use Prisma ORM's existing [`sqlite` database connector](/orm/overview/databases/sqlite) in your schema - use [Prisma Client](/orm/prisma-client) in your application to talk to the database server at D1 ## Differences to consider There are a number of differences between D1 and SQLite to consider. You should be aware of the following when deciding to use D1 and Prisma ORM: - **Making schema changes**. As of [v6.6.0](https://pris.ly/release/6.6.0) and with a `prisma.config.ts` file, you can use `prisma db push`. However, if you prefer a Cloudflare first approach, you can use D1's [migration system](https://developers.cloudflare.com/d1/reference/migrations/) and the [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) command for your migration workflows. See the [Schema migrations with Prisma ORM on D1](#schema-migrations-with-prisma-orm-on-d1) section below for more information. - **Local and remote D1 (SQLite) databases**. Cloudflare provides local and remote versions of D1. The [local](https://developers.cloudflare.com/d1/build-with-d1/local-development/) version is managed using the `--local` option of the `wrangler d1` CLI and is located in `.wrangler/state`. The [remote](https://developers.cloudflare.com/d1/build-with-d1/remote-development/) version is managed by Cloudflare and is accessed via HTTP. ## How to connect to D1 in Cloudflare Workers or Cloudflare Pages When using Prisma ORM with D1, you need to use the `sqlite` database provider and the `@prisma/adapter-d1` [driver adapter](/orm/overview/databases/database-drivers#driver-adapters). If you want to deploy a Cloudflare Worker with D1 and Prisma ORM, follow these [step-by-step instructions](/guides/cloudflare-d1). ## Schema migrations with Prisma ORM on D1 You can use two approaches for migrating your database schema with Prisma ORM and D1: - Using `prisma db push` via a driver adapter in `prisma.config.ts` - Using the Wrangler CLI ### Using Prisma Migrate via a driver adapter in `prisma.config.ts` (Early Access) :::warning This functionality has been introduced in [Early Access](/orm/more/releases#early-access) in [v6.6.0](https://pris.ly/release/6.6.0) and supports the following commands: - `prisma db push` - `prisma db pull` - `prisma migrate diff` Other commands like `prisma migrate dev` and `prisma migrate deploy` will be added soon. ::: #### 1. Install the Prisma D1 driver adapter Run this command in your terminal: ```terminal npm install @prisma/adapter-d1 ``` #### 2. Set environment variables In order to set up the D1 adapter, you'll need to add a few secrets to a `.env` file: - `CLOUDFLARE_ACCOUNT_ID`: Your Cloudflare account ID, fetched via `npx wrangler whoami`. - `CLOUDFLARE_DATABASE_ID`: Retrieved during D1 database creation. If you have an existing D1 database, you can use `npx wrangler d1 list` and `npx wrangler d1 info ` to get the ID. - `CLOUDFLARE_D1_TOKEN`: This API token is used by Prisma ORM to communicate with your D1 instance directly. To create it, follow these steps: 1. Visit https://dash.cloudflare.com/profile/api-tokens 2. Click **Create Token** 3. Click **Custom token** template 4. Fill out the template: Make sure you use a recognizable name and add the **Account / D1 / Edit** permission. 5. Click **Continue to summary** and then **Create Token**. You can then add these to your `.env` file or use them directly if they are stored in a different secret store: ```bash file=.env CLOUDFLARE_ACCOUNT_ID="0773..." CLOUDFLARE_DATABASE_ID="01f30366-..." CLOUDFLARE_D1_TOKEN="F8Cg..." ``` #### 3. Set up Prisma Config file Make sure that you have a [`prisma.config.ts`](/orm/reference/prisma-config-reference) file for your project. Then, set up the [migration driver adapter](/orm/reference/prisma-config-reference#migrateadapter) to reference D1: ```ts file=prisma.config.ts import path from 'node:path' import type { PrismaConfig } from 'prisma' import { PrismaD1HTTP } from '@prisma/adapter-d1' // import your .env file import 'dotenv/config' type Env = { CLOUDFLARE_D1_TOKEN: string CLOUDFLARE_ACCOUNT_ID: string CLOUDFLARE_DATABASE_ID: string } export default { earlyAccess: true, schema: path.join('prisma', 'schema.prisma'), // add-start migrate: { async adapter(env) { return new PrismaD1HTTP({ CLOUDFLARE_D1_TOKEN: env.CLOUDFLARE_D1_TOKEN, CLOUDFLARE_ACCOUNT_ID: env.CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_DATABASE_ID: env.CLOUDFLARE_DATABASE_ID, }) }, }, // add-end } satisfies PrismaConfig ``` #### 4. Migrate your database Prisma Migrate now will run migrations against your remote D1 database based on the configuration provided in `prisma.config.ts`. To update the remote schema with this workflow, run the following command: ```terminal npx prisma db push ``` :::note Note that for querying the database, you keep using the `PrismaD1` driver adapter from the `@prisma/adapter-d1` package: ```ts import { PrismaD1HTTP } from '@prisma/adapter-d1' ``` ::: ### Using the Wrangler CLI Cloudflare D1 comes with its own [migration system](https://developers.cloudflare.com/d1/reference/migrations/). While we recommend that you use the [native Prisma Migrate workflow](#using-prisma-migrate-via-a-driver-adapter-in-prismaconfigts-early-access), this migration system via the `wrangler d1 migrations` command is available. This command doesn't help you in figuring out the SQL statements for creating your database schema that need to be put _inside_ of these migration files though. If you want to query your database using Prisma Client, it's important that your database schema maps to your Prisma schema, this is why it's recommended to generate the SQL statements from your Prisma schema. When using D1, you can use the [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) command for that purpose. #### Creating an initial migration The workflow for creating an initial migration looks as follows. Assume you have a fresh D1 instance without any tables. ##### 1. Update your Prisma data model This is your initial version of the Prisma schema that you want to map to your D1 instance: ```prisma model User { id Int @id @default(autoincrement()) email String @unique name String? } ``` ##### 2. Create migration file using `wrangler` CLI Next, you need to create the migration file using the [`wrangler d1 migrations create`](https://developers.cloudflare.com/workers/wrangler/commands/#migrations-create) command: ```terminal npx wrangler d1 migrations create __YOUR_DATABASE_NAME__ create_user_table ``` Since this is the very first migration, this command will prompt you to also create a `migrations` folder. Note that if you want your migration files to be stored in a different location, you can [customize it using Wrangler](https://developers.cloudflare.com/d1/reference/migrations/#wrangler-customizations). Once the command has executed and assuming you have chosen the default `migrations` name for the location of your migration files, the command has created the following folder and file for you: ```no-copy migrations/ └── 0001_create_user_table.sql ``` However, before you can apply the migration to your D1 instance, you actually need to put a SQL statement into the currently empty `0001_create_user_table.sql` file. ##### 3. Generate SQL statements using `prisma migrate diff` To generate the initial SQL statement, you can use the `prisma migrate diff` command which compares to _schemas_ (via its `--to-X` and `--from-X` options) and generates the steps that are needed to "evolve" from one to the other. These schemas can be either Prisma or SQL schemas. For the initial migration, you can use the special `--from-empty` option though: ```terminal npx prisma migrate diff \ --from-empty \ --to-schema-datamodel ./prisma/schema.prisma \ --script \ --output migrations/0001_create_user_table.sql ``` The command above uses the following options: - `--from-empty`: The source for the SQL statement is an empty schema. - `--to-schema-datamodel ./prisma/schema.prisma`: The target for the SQL statement is the data model in `./prisma/schema.prisma`. - `--script`: Output the result as SQL. If you omit this option, the "migration steps" will be generated in plain English. - `--output migrations/0001_create_user_table.sql`: Store the result in `migrations/0001_create_user_table.sql`. After running this command, `migrations/0001_create_user_table.sql` will have the following contents: ```sql file=migrations/0001_create_user_table.sql no-copy -- CreateTable CREATE TABLE "User" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "email" TEXT NOT NULL, "name" TEXT ); -- CreateIndex CREATE UNIQUE INDEX "User_email_key" ON "User"("email"); ``` ##### 4. Execute the migration using `wrangler d1 migrations apply` Finally, you can apply the migration against your D1 instances. For the **local** instance, run: ```terminal npx wrangler d1 migrations apply __YOUR_DATABASE_NAME__ --local ``` For the **remote** instance, run: ```terminal npx wrangler d1 migrations apply __YOUR_DATABASE_NAME__ --remote ``` #### Evolve your schema with further migrations For any further migrations, you can use the same workflow but instead of using `--from-empty`, you'll need to use `--from-local-d1` because your source schema for the `prisma migrate diff` command now is the current schema of that local D1 instance, while the target remains your (then updated) Prisma schema. ##### 1. Update your Prisma data model Assume you have updated your Prisma schema with another model: ```prisma model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } model Post { id Int @id @default(autoincrement()) title String author User @relation(fields: [authorId], references: [id]) authorId Int } ``` ##### 2. Create migration file using `wrangler` CLI Like before, you first need to create the migration file: ```terminal npx wrangler d1 migrations create __YOUR_DATABASE_NAME__ create_post_table ``` Once the command has executed (again assuming you have chosen the default `migrations` name for the location of your migration files), the command has created a new file inside of the `migrations` folder: ```no-copy migrations/ ├── 0001_create_user_table.sql └── 0002_create_post_table.sql ``` As before, you now need to put a SQL statement into the currently empty `0002_create_post_table.sql` file. ##### 3. Generate SQL statements using `prisma migrate diff` As explained above, you now need to use `--from-local-d1` instead of `--from-empty` to specify a source schema: ```terminal npx prisma migrate diff \ --from-local-d1 \ --to-schema-datamodel ./prisma/schema.prisma \ --script \ --output migrations/0002_create_post_table.sql ``` The command above uses the following options: - `--from-local-d1`: The source for the SQL statement is the local D1 database file. - `--to-schema-datamodel ./prisma/schema.prisma`: The target for the SQL statement is the data model in `./prisma/schema.prisma`. - `--script`: Output the result as SQL. If you omit this option, the "migration steps" will be generated in plain English. - `--output migrations/0002_create_post_table.sql`: Store the result in `migrations/0002_create_post_table.sql`. After running this command, `migrations/0002_create_post_table.sql` will have the following contents: ```sql file=migrations/0002_create_post_table.sql no-copy -- CreateTable CREATE TABLE "Post" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "title" TEXT NOT NULL, "authorId" INTEGER NOT NULL, CONSTRAINT "Post_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User" ("id") ON DELETE RESTRICT ON UPDATE CASCADE ); ``` ##### 4. Execute the migration using `wrangler d1 migrations apply` Finally, you can apply the migration against your D1 instances. For the **local** instance, run: ```terminal npx wrangler d1 migrations apply __YOUR_DATABASE_NAME__ --local ``` For the **remote** instance, run: ```terminal npx wrangler d1 migrations apply __YOUR_DATABASE_NAME__ --remote ``` ## Limitations ### Transactions not supported Cloudflare D1 currently does not support transactions (see the [open feature request](https://github.com/cloudflare/workers-sdk/issues/2733)). As a result, Prisma ORM does not support transactions for Cloudflare D1. When using Prisma's D1 adapter, implicit & explicit transactions will be ignored and run as individual queries, which breaks the guarantees of the ACID properties of transactions. ### Prisma Migrate only supports remote D1 databases The Wrangler CLI can distinguish between local and remote D1 (i.e. SQLite) database instances via the `--local` and `--remote` options. This distinction is currently not available with the [native Prisma Migrate workflow](#using-prisma-migrate-via-a-driver-adapter-in-prismaconfigts-early-access). --- # Databases URL: https://www.prisma.io/docs/orm/overview/databases/index Learn about the different databases Prisma ORM supports. ## In this section --- # Beyond Prisma ORM URL: https://www.prisma.io/docs/orm/overview/beyond-prisma-orm As a Prisma ORM user, you're already experiencing the power of type-safe database queries and intuitive data modeling. When scaling production applications, however, new challenges emerge. As an app matures it’s a given that you’ll begin to experience connection pooling complexities or find ways to effectively cache common queries. Instead of spending your valuable time overcoming these challenges, let’s explore how Prisma can help by extending the capabilities of the ORM as your application grows. ## Boost application performance with Prisma Accelerate As your application scales, you'll likely need tools to handle increased traffic efficiently. This often involves implementing connection pooling to manage database connections and caching strategies to reduce database load and improve response times. Prisma Accelerate addresses these needs in a single solution, eliminating the need to set up and manage separate infrastructure. Prisma Accelerate is particularly useful for applications deployed to serverless and edge environments (also know as Function-as-a-Service) because these deployments lend themselves towards many orders of magnitude more connections being created than a traditional, long-lived application. For these apps, Prisma Accelerate has the added benefit of protecting your database from day one and keeping your app online [regardless of traffic you experience](https://www.prisma.io/blog/saving-black-friday-with-connection-pooling). Try out the [Accelerate speed test](https://accelerate-speed-test.prisma.io/) to see what’s possible. ### Improve query performance with connection pooling Place your connection pooler in one of 15+ global regions, minimizing latency for database operations. Enable high-performance distributed workloads across serverless and edge environments. ### Reduce query latency and database load with caching Cache query results across 300+ global points of presence. Accelerate extends your Prisma Client, offering intuitive, granular control over caching patterns such as `ttl` and `swr` on a per-query basis. ### Handle scaling traffic with managed infrastructure Scale to millions of queries per day without infrastructure changes. Efficiently manage database connections and serve more users with fewer resources. ### Get started with Accelerate today Accelerate integrates seamlessly with your Prisma ORM project through the `@prisma/extension-accelerate` client extension. Get started quickly with our [setup guide](/accelerate/getting-started) and instantly access full edge environment support, connection pooling, and global caching. ```tsx import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' // 1. Extend your Prisma Client with the Accelerate extension const prisma = new PrismaClient().$extends(withAccelerate()) // 2. (Optionally) add cache to your Prisma queries const users = await prisma.user.findMany({ cacheStrategy: { ttl: 30, // Consider data fresh for 30 seconds swr: 60 // Serve stale data for up to 60 seconds while fetching fresh data } }) ``` To see more examples, visit our [examples repo](https://github.com/prisma/prisma-examples) or try them out yourself with `npx try-prisma`. [Sign up for Accelerate](https://console.prisma.io/login) ## Grow with Prisma Prisma Accelerate take features built into Prisma ORM and build upon them by adding additional capabilities like globally-optimized caching and connection pooling. Get started for free the [Prisma Data Platform](https://console.prisma.io/login) and explore how Accelerate can help you build scalable, high-performance applications! Improving developer experience doesn’t stop at Accelerate. Prisma is building and expanding our products, such as [Prisma Optimize](https://www.prisma.io/optimize) and [Prisma Postgres](https://www.prisma.io/postgres), to improve every aspect of Data DX and we’d love to hear what you think. Join our community and learn more about our products below. Accelerate and Optimize build on Prisma ORM through [Prisma Client Extensions](/orm/prisma-client/client-extensions). This opens up features that we couldn’t include in the ORM like globally-optimized caching and connection pooling. Create a free [Prisma Data Platform](https://console.prisma.io/login) account and explore how Accelerate can help you build scalable, high-performance applications! Improving developer experience doesn’t stop at Prisma Postgres, Accelerate and Optimize. Prisma is building and expanding our products to improve every aspect of Data DX and we’d love to hear what you think. Join our community and learn more about our products below
[Accelerate](https://www.prisma.io/accelerate?utm_source=docs&utm_medium=orm-docs)
[Optimize](https://www.prisma.io/optimize?utm_source=docs&utm_medium=orm-docs)
[Prisma Postgres](https://www.prisma.io/postgres?utm_source=docs&utm_medium=orm-docs)
--- # Overview URL: https://www.prisma.io/docs/orm/overview/index ## In this section --- # Data sources URL: https://www.prisma.io/docs/orm/prisma-schema/overview/data-sources A data source determines how Prisma ORM connects your database, and is represented by the [`datasource`](/orm/reference/prisma-schema-reference#datasource) block in the Prisma schema. The following data source uses the `postgresql` provider and includes a connection URL: ```prisma datasource db { provider = "postgresql" url = "postgresql://johndoe:mypassword@localhost:5432/mydb?schema=public" } ``` A Prisma schema can only have _one_ data source. However, you can: - [Programmatically override a data source `url` when creating your `PrismaClient`](/orm/reference/prisma-client-reference#programmatically-override-a-datasource-url) - [Specify a different URL for Prisma Migrate's shadow database if you are working with cloud-hosted development databases](/orm/prisma-migrate/understanding-prisma-migrate/shadow-database#cloud-hosted-shadow-databases-must-be-created-manually) > **Note**: Multiple provider support was removed in 2.22.0. Please see [Deprecation of provider array notation](https://github.com/prisma/prisma/issues/3834) for more information. ## Securing database connections Some data source `provider`s allow you to configure your connection with SSL/TLS, and provide parameters for the `url` to specify the location of certificates. - [Configuring an SSL connection with PostgreSQL](/orm/overview/databases/postgresql#configuring-an-ssl-connection) - [Configuring an SSL connection with MySQL](/orm/overview/databases/mysql#configuring-an-ssl-connection) - [Configure a TLS connection with Microsoft SQL Server](/orm/overview/databases/sql-server#connection-details) Prisma ORM resolves SSL certificates relative to the `./prisma` directory. If your certificate files are located outside that directory, e.g. your project root directory, use relative paths for certificates: **Note:** When the [`prismaSchemaFolder`](/orm/prisma-schema/overview/location#multi-file-prisma-schema-preview) preview feature is enabled, Prisma ORM resolves SSL certificates relative to the `./prisma/schema` directory. ```prisma datasource db { provider = "postgresql" url = "postgresql://johndoe:mypassword@localhost:5432/mydb?schema=public&sslmode=require&sslcert=../server-ca.pem&sslidentity=../client-identity.p12&sslpassword=" } ``` --- # Generators URL: https://www.prisma.io/docs/orm/prisma-schema/overview/generators A Prisma schema can have one or more generators, represented by the [`generator`](/orm/reference/prisma-schema-reference#generator) block: ```prisma generator client { provider = "prisma-client-js" output = "./generated/prisma-client-js" } ``` A generator determines which assets are created when you run the `prisma generate` command. There are two generators for Prisma Client: - `prisma-client-js`: Generates Prisma Client into `node_modules` - `prisma-client` ([Early Access](/orm/more/releases#early-access)): Newer and more flexible version of `prisma-client-js` with ESM support; it outputs plain TypeScript code and _requires_ a custom `output` path Alternatively, you can configure any npm package that complies with our generator specification. ## `prisma-client-js` The `prisma-client-js` is the default generator for Prisma ORM 6.X versions and before. It requires the `@prisma/client` npm package and generates Prisma Client into `node_modules`. ### Field reference The generator for Prisma's JavaScript Client accepts multiple additional properties: - `previewFeatures`: [Preview features](/orm/reference/preview-features) to include - `binaryTargets`: Engine binary targets for `prisma-client-js` (for example, `debian-openssl-1.1.x` if you are deploying to Ubuntu 18+, or `native` if you are working locally) ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["sample-preview-feature"] binaryTargets = ["debian-openssl-1.1.x"] // defaults to `"native"` } ``` ### Binary targets The `prisma-client-js` generator uses several [engines](https://github.com/prisma/prisma-engines). Engines are implemented in Rust and are used by Prisma Client in the form of executable, platform-dependent engine files. Depending on which platform you are executing your code on, you need the correct file. "Binary targets" are used to define which files should be present for the target platform(s). The correct file is particularly important when [deploying](/orm/prisma-client/deployment/deploy-prisma) your application to production, which often differs from your local development environment. #### The `native` binary target The `native` binary target is special. It doesn't map to a concrete operating system. Instead, when `native` is specified in `binaryTargets`, Prisma Client detects the _current_ operating system and automatically specifies the correct binary target for it. As an example, assume you're running **macOS** and you specify the following generator: ```prisma file=prisma/schema.prisma generator client { provider = "prisma-client-js" binaryTargets = ["native"] } ``` In that case, Prisma Client detects your operating system and finds the right binary file for it based on the [list of supported operating systems](/orm/reference/prisma-schema-reference#binarytargets-options) . If you use macOS Intel x86 (`darwin`), then the binary file that was compiled for `darwin` will be selected. If you use macOS ARM64 (`darwin-arm64`), then the binary file that was compiled for `darwin-arm64` will be selected. > **Note**: The `native` binary target is the default. You can set it explicitly if you wish to include additional [binary targets](/orm/reference/prisma-schema-reference#binarytargets-options) for deployment to different environments. ## `prisma-client` (Early Access) The new `prisma-client` generator offers greater control and flexibility when using Prisma ORM across different JavaScript environments (such as ESM, Bun, Deno, ...). It generates Prisma Client into a custom directory in your application's codebase that's specified via the `output` field on the `generator` block. This gives you full visibility and control over the generated code, including the query engine. Currently in [Early Access](/orm/more/releases#early-access), this generator ensures you can bundle your application code exactly the way you want, without relying on hidden or automatic behaviors. Here are the main differences compared to `prisma-client-js`: - Requires an `output` path; no “magic” generation into `node_modules` any more - Supports ESM and CommonJS via the `moduleFormat` field - More flexible thanks to additional fields - Outputs plain TypeScript that's bundled just like the rest of your application code The `prisma-client` generator will become the new default with Prisma ORM v7. ### Getting started Follow these steps to use the new `prisma-client` generator in your project. #### 1. Configure the `prisma-client` generator in `schema.prisma` Update your [`generator`](/orm/prisma-schema/overview/generators) block: ```prisma file=prisma/schema.prisma generator client { //add-start provider = "prisma-client" // Required output = "../src/generated/prisma" // Required path //add-end } ``` The **`output` option is required** and tells Prisma ORM where to put the generated Prisma Client code. You can choose any location suitable for your project structure. For instance, if you have the following layout: ```txt . ├── package.json ├── prisma │ └── schema.prisma ├── src │ └── index.ts └── tsconfig.json ``` Then `../src/generated/prisma` places the generated code in `src/generated/prisma` relative to `schema.prisma`. #### 2. Generate Prisma Client Generate Prisma Client by running: ```bash npx prisma generate ``` This generates the code for Prisma Client (including the query engine binary) into the specified `output` folder. #### 3. Exclude the generated directory from version control The new generator includes both the TypeScript client code _and_ the [query engine](/orm/more/under-the-hood/engines#the-query-engine-file). Including the query engine in version control can cause compatibility issues on different machines. To avoid this, add the generated directory to `.gitignore`: ```bash file=.gitignore # Keep the generated Prisma Client + query engine out of version control /src/generated/prisma ``` :::note In the future, you can safely include the generated directory in version control when [Prisma ORM is fully transitioned from Rust to TypeScript](https://www.prisma.io/blog/rust-to-typescript-update-boosting-prisma-orm-performance?utm_source=docs&utm_medium=inline_text). ::: #### 4. Use Prisma Client in your application After generating the Prisma Client, import the types from the path you specified: ```ts file=src/index.ts import { PrismaClient } from "./generated/prisma/client" const prisma = new PrismaClient() ``` Prisma Client is now ready to use in your project. ### Field reference Use the following options in the `generator client { ... }` block. Only `output` is required. The other fields have defaults or are inferred from your environment and `tsconfig.json`. ```prisma file=schema.prisma generator client { // Required provider = "prisma-client" output = "../src/generated/prisma" // Optional runtime = "nodejs" moduleFormat = "esm" generatedFileExtension = "ts" importFileExtension = "ts" } ``` Below are the options for the `prisma-client` generator: | **Option** | **Default** | **Description** | | ------------------------ | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `output` (**required**) | | Directory where Prisma Client is generated, e.g. `../src/generated/prisma`. | | `runtime` | `nodejs` | Target runtime environment.
Supported values:
`nodejs` (alias `node`), `deno`, `bun`, `deno-deploy`, `workerd` (alias `cloudflare`), `edge-light` (alias `vercel`), `react-native`. | | `moduleFormat` | Inferred from environment | Module format (`esm` or `cjs`). Determines whether `import.meta.url` or `__dirname` is used. | | `generatedFileExtension` | `ts` | File extension for generated TypeScript files (`ts`, `mts`, `cts`). | | `importFileExtension` | Inferred from environment | File extension used in **import statements**. Can be `ts`, `mts`, `cts`, `js`, `mjs`, `cjs`, or empty (for bare imports). | ### Limitations - **Namespace usage**: The generated code still relies on TypeScript features like `namespace`, which may cause incompatibility with certain runtime-only setups (e.g., Node.js 22+ without `--experimental-transform-types`). It remains fully compatible with standard runtimes, `tsx`, `ts-node`, and most bundlers. - **No browser bundle**: There is currently no official browser build, and importing types or enums in frontend code is not supported. :::note Both limitations will be resolved soon in a future release. ::: ## Community generators :::note Existing generators or new ones should not be affected if you are using the [`prismaSchemaFolder`](/orm/reference/preview-features/client-preview-features#currently-active-preview-features) preview feature to manage multiple schema files, unless a generator reads the schema manually. ::: The following is a list of community created generators. - [`prisma-dbml-generator`](https://notiz.dev/blog/prisma-dbml-generator/): Transforms the Prisma schema into [Database Markup Language](https://dbml.dbdiagram.io/home/) (DBML) which allows for an easy visual representation - [`prisma-docs-generator`](https://github.com/pantharshit00/prisma-docs-generator): Generates an individual API reference for Prisma Client - [`prisma-json-schema-generator`](https://github.com/valentinpalkovic/prisma-json-schema-generator): Transforms the Prisma schema in [JSON schema](https://json-schema.org/) - [`prisma-json-types-generator`](https://github.com/arthurfiorette/prisma-json-types-generator): Adds support for [Strongly Typed `Json`](https://github.com/arthurfiorette/prisma-json-types-generator#readme) fields for all databases. It goes on `prisma-client-js` output and changes the json fields to match the type you provide. Helping with code generators, intellisense and much more. All of that without affecting any runtime code. - [`typegraphql-prisma`](https://github.com/MichalLytek/typegraphql-prisma#readme): Generates [TypeGraphQL](https://typegraphql.com/) CRUD resolvers for Prisma models - [`typegraphql-prisma-nestjs`](https://github.com/EndyKaufman/typegraphql-prisma-nestjs#readme): Fork of [`typegraphql-prisma`](https://github.com/MichalLytek/typegraphql-prisma), which also generates CRUD resolvers for Prisma models but for NestJS - [`prisma-typegraphql-types-gen`](https://github.com/YassinEldeeb/prisma-tgql-types-gen): Generates [TypeGraphQL](https://typegraphql.com/) class types and enums from your prisma type definitions, the generated output can be edited without being overwritten by the next gen and has the ability to correct you when you mess up the types with your edits. - [`nexus-prisma`](https://github.com/prisma/nexus-prisma/): Allows to project Prisma models to GraphQL via [GraphQL Nexus](https://nexusjs.org/docs/) - [`prisma-nestjs-graphql`](https://github.com/unlight/prisma-nestjs-graphql): Generates object types, inputs, args, etc. from the Prisma Schema for usage with `@nestjs/graphql` module - [`prisma-appsync`](https://github.com/maoosi/prisma-appsync): Generates a full-blown GraphQL API for [AWS AppSync](https://aws.amazon.com/appsync/) - [`prisma-kysely`](https://github.com/valtyr/prisma-kysely): Generates type definitions for Kysely, a TypeScript SQL query builder. This can be useful to perform queries against your database from an edge runtime, or to write more complex SQL queries not possible in Prisma without dropping type safety. - [`prisma-generator-nestjs-dto`](https://github.com/vegardit/prisma-generator-nestjs-dto): Generates DTO and Entity classes with relation `connect` and `create` options for use with [NestJS Resources](https://docs.nestjs.com/recipes/crud-generator) and [@nestjs/swagger](https://www.npmjs.com/package/@nestjs/swagger) - [`prisma-erd-generator`](https://github.com/keonik/prisma-erd-generator): Generates an entity relationship diagram - [`prisma-generator-plantuml-erd`](https://github.com/dbgso/prisma-generator-plantuml-erd/tree/main/packages/generator): Generator to generate ER diagrams for PlantUML. Markdown and Asciidoc documents can also be generated by activating the option. - [`prisma-class-generator`](https://github.com/kimjbstar/prisma-class-generator): Generates classes from your Prisma Schema that can be used as DTO, Swagger Response, TypeGraphQL and so on. - [`zod-prisma`](https://github.com/CarterGrimmeisen/zod-prisma): Creates Zod schemas from your Prisma models. - [`prisma-pothos-types`](https://github.com/hayes/pothos/tree/main/packages/plugin-prisma): Makes it easier to define Prisma-based object types, and helps solve n+1 queries for relations. It also has integrations for the Relay plugin to make defining nodes and connections easy and efficient. - [`prisma-generator-pothos-codegen`](https://github.com/Cauen/prisma-generator-pothos-codegen): Auto generate input types (for use as args) and auto generate decoupled type-safe base files makes it easy to create customizable objects, queries and mutations for [Pothos](https://pothos-graphql.dev/) from Prisma schema. Optionally generate all crud at once from the base files. - [`prisma-joi-generator`](https://github.com/omar-dulaimi/prisma-joi-generator): Generate full Joi schemas from your Prisma schema. - [`prisma-yup-generator`](https://github.com/omar-dulaimi/prisma-yup-generator): Generate full Yup schemas from your Prisma schema. - [`prisma-class-validator-generator`](https://github.com/omar-dulaimi/prisma-class-validator-generator): Emit TypeScript models from your Prisma schema with class validator validations ready. - [`prisma-zod-generator`](https://github.com/omar-dulaimi/prisma-zod-generator): Emit Zod schemas from your Prisma schema. - [`prisma-trpc-generator`](https://github.com/omar-dulaimi/prisma-trpc-generator): Emit fully implemented tRPC routers. - [`prisma-json-server-generator`](https://github.com/omar-dulaimi/prisma-json-server-generator): Emit a JSON file that can be run with json-server. - [`prisma-trpc-shield-generator`](https://github.com/omar-dulaimi/prisma-trpc-shield-generator): Emit a tRPC shield from your Prisma schema. - [`prisma-custom-models-generator`](https://github.com/omar-dulaimi/prisma-custom-models-generator): Emit custom models from your Prisma schema, based on Prisma recommendations. - [`nestjs-prisma-graphql-crud-gen`](https://github.com/mk668a/nestjs-prisma-graphql-crud-gen): Generate CRUD resolvers from GraphQL schema with NestJS and Prisma. - [`prisma-generator-dart`](https://github.com/FredrikBorgstrom/abcx3/tree/master/libs/prisma-generator-dart): Generates Dart/Flutter class files with to- and fromJson methods. - [`prisma-generator-graphql-typedef`](https://github.com/mavvy22/prisma-generator-graphql-typedef): Generates graphql schema. - [`prisma-markdown`](https://github.com/samchon/prisma-markdown): Generates markdown document composed with ERD diagrams and their descriptions. Supports pagination of ERD diagrams through `@namespace` comment tag. - [`prisma-models-graph`](https://github.com/dangchinh25/prisma-models-graph): Generates a bi-directional models graph for schema without strict relationship defined in the schema, works via a custom schema annotation. - [`prisma-generator-fake-data`](https://github.com/luisrudge/prisma-generator-fake-data): Generates realistic-looking fake data for your Prisma models that can be used in unit/integration tests, demos, and more. - [`prisma-generator-drizzle`](https://github.com/farreldarian/prisma-generator-drizzle): A Prisma generator for generating Drizzle schema with ease. - [`prisma-generator-express`](https://github.com/multipliedtwice/prisma-generator-express): Generates Express CRUD and Router generator function. - [`prismabox`](https://github.com/m1212e/prismabox): Generates versatile [typebox](https://github.com/sinclairzx81/typebox) schema from your Prisma models. - [`prisma-generator-typescript-interfaces`](https://github.com/mogzol/prisma-generator-typescript-interfaces): Generates zero-dependency TypeScript interfaces from your Prisma schema. --- # Schema location URL: https://www.prisma.io/docs/orm/prisma-schema/overview/location The default name for the Prisma Schema is a single file `schema.prisma` in your `prisma` folder. When your schema is named like this, the Prisma CLI will detect it automatically. > If you are using the [`prismaSchemaFolder` preview feature](#multi-file-prisma-schema-preview) any files in the `prisma/schema` directory are detected automatically. ## Prisma Schema location The Prisma CLI looks for the Prisma Schema in the following locations, in the following order: 1. The location specified by the [`--schema` flag](/orm/reference/prisma-cli-reference), which is available when you `introspect`, `generate`, `migrate`, and `studio`: ```terminal prisma generate --schema=./alternative/schema.prisma ``` 2. The location specified in the `package.json` file (version 2.7.0 and later): ```json "prisma": { "schema": "db/schema.prisma" } ``` 3. Default locations: - `./prisma/schema.prisma` - `./schema.prisma` The Prisma CLI outputs the path of the schema that will be used. The following example shows the terminal output for `prisma db pull`: ```no-lines Environment variables loaded from .env //highlight-next-line Prisma Schema loaded from prisma/schema.prisma Introspecting based on datasource defined in prisma/schema.prisma … ✔ Introspected 4 models and wrote them into prisma/schema.prisma in 239ms Run prisma generate to generate Prisma Client. ``` ## Multi-file Prisma Schema (Preview) If you prefer splitting your Prisma schema into multiple files, you can have a setup that looks as follows: ``` my-app/ ├─ ... ├─ prisma/ │ ├─ schema/ │ │ ├─ post.prisma │ │ ├─ schema.prisma │ │ ├─ user.prisma ├─ ... ``` ### Usage You can split your Prisma schema into multiple files by enabling the `prismaSchemaFolder` Preview feature on your `generator` block: ```prisma file=schema.prisma generator client { provider = "prisma-client-js" //add-next-line previewFeatures = ["prismaSchemaFolder"] } ``` As of [v6.6.0](https://github.com/prisma/prisma/releases/tag/6.6.0), you must always explicitly specify the location of your Prisma schema folder. There is no "magic" detection of the Prisma schema folder in a default location any more. You can do this in either of three ways: - pass the the `--schema` option to your Prisma CLI command (e.g. `prisma migrate dev --schema ./prisma/schema`) - set the `prisma.schema` field in `package.json`: ```jsonc // package.json { "prisma": { "schema": "./schema" } } ``` - set the `schema` property in [`prisma.config.ts`](/orm/reference/prisma-config-reference#schema): ```ts import path from 'node:path' import type { PrismaConfig } from 'prisma' export default { earlyAccess: true, schema: path.join('prisma', 'schema'), } satisfies PrismaConfig ``` You also must place the `migrations` directory next to the `.prisma` file that defines the `datasource` block. For example, assuming `schema.prisma` defines the `datasource`, here's how how need to place the migrations folder: ``` # `migrations` and `schema.prisma` are on the same level . ├── migrations ├── models │ ├── posts.prisma │ └── users.prisma └── schema.prisma ``` ### How to use existing Prisma CLI commands with multiple Prisma schema files For most Prisma CLI commands, no changes will be necessary to work with a multi-file Prisma schema. Only in the specific cases where you need to supply a schema via an option will a command need to be changed. In these cases, simply replace references to a file with a directory. As an example, the following `prisma db push` command: ```terminal npx prisma db push --schema custom/path/to/my/schema.prisma ``` becomes the following: ```terminal npx prisma db push --schema custom/path/to/my/schema # note this is now a directory! ``` ### Tips for multi-file Prisma Schema We’ve found that a few patterns work well with this feature and will help you get the most out of it: - Organize your files by domain: group related models into the same file. For example, keep all user-related models in `user.prisma` while post-related models go in `post.prisma`. Try to avoid having “kitchen sink” schema files. - Use clear naming conventions: schema files should be named clearly and succinctly. Use names like `user.prisma` and `post.prisma` and not `myModels.prisma` or `CommentFeaturesSchema.prisma`. - Have an obvious “main” schema file: while you can now have as many schema files as you want, you’ll still need a place where you define `datasource` and `generator` blocks. We recommend having a single schema file that’s obviously the “main” file so that these blocks are easy to find. `main.prisma`, `schema.prisma`, and `base.prisma` are a few we’ve seen that work well. ### Examples Our fork of [`dub` by dub.co](https://github.com/prisma/dub) is a great example of a real world project adapted to use a multi-file Prisma Schema. ### Learn more about the `prismaSchemaFolder` preview feature To give feedback on the `prismaSchemaFolder` Preview feature, please refer to [our dedicated Github discussion](https://github.com/prisma/prisma/discussions/24413). --- # Overview URL: https://www.prisma.io/docs/orm/prisma-schema/overview/index The Prisma Schema (or _schema_ for short) is the main method of configuration for your Prisma ORM setup. It consists of the following parts: - [**Data sources**](/orm/prisma-schema/overview/data-sources): Specify the details of the data sources Prisma ORM should connect to (e.g. a PostgreSQL database) - [**Generators**](/orm/prisma-schema/overview/generators): Specifies what clients should be generated based on the data model (e.g. Prisma Client) - [**Data model definition**](/orm/prisma-schema/data-model): Specifies your application [models](/orm/prisma-schema/data-model/models#defining-models) (the shape of the data per data source) and their [relations](/orm/prisma-schema/data-model/relations) It is typically a single file called `schema.prisma` (or multiple files with `.prisma` file extension) that is stored in a defined but customizable [location](/orm/prisma-schema/overview/location). :::note Looking to split your schema into multiple files? Multi-file Prisma Schema is supported via the [`prismaSchemaFolder` preview feature](/orm/prisma-schema/overview/location#multi-file-prisma-schema-preview) in Prisma ORM 5.15.0 and later. ::: See the [Prisma schema API reference](/orm/reference/prisma-schema-reference) for detailed information about each section of the schema. Whenever a `prisma` command is invoked, the CLI typically reads some information from the schema, e.g.: - `prisma generate`: Reads _all_ above mentioned information from the Prisma schema to generate the correct data source client code (e.g. Prisma Client). - `prisma migrate dev`: Reads the data sources and data model definition to create a new migration. You can also [use environment variables](#accessing-environment-variables-from-the-schema) inside the schema to provide configuration options when a CLI command is invoked. ## Example The following is an example of a Prisma Schema that specifies: - A data source (PostgreSQL or MongoDB) - A generator (Prisma Client) - A data model definition with two models (with one relation) and one `enum` - Several [native data type attributes](/orm/prisma-schema/data-model/models#native-types-mapping) (`@db.VarChar(255)`, `@db.ObjectId`) ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model User { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) email String @unique name String? role Role @default(USER) posts Post[] } model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt published Boolean @default(false) title String @db.VarChar(255) author User? @relation(fields: [authorId], references: [id]) authorId Int? } enum Role { USER ADMIN } ``` ```prisma datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model User { id String @id @default(auto()) @map("_id") @db.ObjectId createdAt DateTime @default(now()) email String @unique name String? role Role @default(USER) posts Post[] } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId createdAt DateTime @default(now()) updatedAt DateTime @updatedAt published Boolean @default(false) title String author User? @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId } enum Role { USER ADMIN } ``` ## Syntax Prisma Schema files are written in Prisma Schema Language (PSL). See the [data sources](/orm/prisma-schema/overview/data-sources), [generators](/orm/prisma-schema/overview/generators), [data model definition](/orm/prisma-schema/data-model) and of course [Prisma Schema API reference](/orm/reference/prisma-schema-reference) pages for details and examples. ### VS Code Syntax highlighting for PSL is available via a [VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) (which also lets you auto-format the contents of your Prisma schema and indicates syntax errors with red squiggly lines). Learn more about [setting up Prisma ORM in your editor](/orm/more/development-environment/editor-setup). ### GitHub PSL code snippets on GitHub can be rendered with syntax highlighting as well by using the `.prisma` file extension or annotating fenced code blocks in Markdown with `prisma`: ```` ```prisma model User { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) email String @unique name String? } ``` ```` ## Accessing environment variables from the schema You can use environment variables to provide configuration options when a CLI command is invoked, or a Prisma Client query is run. Hardcoding URLs directly in your schema is possible but is discouraged because it poses a security risk. Using environment variables in the schema allows you to **keep secrets out of the schema** which in turn **improves the portability of the schema** by allowing you to use it in different environments. Environment variables can be accessed using the `env()` function: ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` You can use the `env()` function in the following places: - A datasource url - Generator binary targets See [Environment variables](/orm/more/development-environment/environment-variables) for more information about how to use an `.env` file during development. ## Comments There are two types of comments that are supported in Prisma Schema Language: - `// comment`: This comment is for the reader's clarity and is not present in the abstract syntax tree (AST) of the schema. - `/// comment`: These comments will show up in the abstract syntax tree (AST) of the schema as descriptions to AST nodes. Tools can then use these comments to provide additional information. All comments are attached to the next available node - [free-floating comments](https://github.com/prisma/prisma/issues/3544) are not supported and are not included in the AST. Here are some different examples: ```prisma /// This comment will get attached to the `User` node in the AST model User { /// This comment will get attached to the `id` node in the AST id Int @default(autoincrement()) // This comment is just for you weight Float /// This comment gets attached to the `weight` node } // This comment is just for you. It will not // show up in the AST. /// This comment will get attached to the /// Customer node. model Customer {} ``` ## Auto formatting Prisma ORM supports formatting `.prisma` files automatically. There are two ways to format `.prisma` files: - Run the [`prisma format`](/orm/reference/prisma-cli-reference#format) command. - Install the [Prisma VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) and invoke the [VS Code format action](https://code.visualstudio.com/docs/editor/codebasics#_formatting) - manually or on save. There are no configuration options - [formatting rules](#formatting-rules) are fixed (similar to Golang's `gofmt` but unlike Javascript's `prettier`): ### Formatting rules #### Configuration blocks are aligned by their `=` sign ``` block _ { key = "value" key2 = 1 long_key = true } ``` #### Field definitions are aligned into columns separated by 2 or more spaces ``` block _ { id String @id first_name LongNumeric @default } ``` #### Empty lines resets block alignment and formatting rules ``` block _ { key = "value" key2 = 1 key10 = true long_key = true long_key_2 = true } ``` ``` block _ { id String @id @default first_name LongNumeric @default } ``` #### Multiline field attributes are properly aligned with the rest of the field attributes ``` block _ { id String @id @default first_name LongNumeric @default } ``` #### Block attributes are sorted to the end of the block ``` block _ { key = "value" @@attribute } ``` --- # Models URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/models The data model definition part of the [Prisma schema](/orm/prisma-schema) defines your application models (also called **Prisma models**). Models: - Represent the **entities** of your application domain - Map to the **tables** (relational databases like PostgreSQL) or **collections** (MongoDB) in your database - Form the foundation of the **queries** available in the generated [Prisma Client API](/orm/prisma-client) - When used with TypeScript, Prisma Client provides generated **type definitions** for your models and any [variations](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types) of them to make database access entirely type safe. The following schema describes a blogging platform - the data model definition is highlighted: ```prisma highlight=10-46;normal datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } //highlight-start model User { id Int @id @default(autoincrement()) email String @unique name String? role Role @default(USER) posts Post[] profile Profile? } model Profile { id Int @id @default(autoincrement()) bio String user User @relation(fields: [userId], references: [id]) userId Int @unique } model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int categories Category[] } model Category { id Int @id @default(autoincrement()) name String posts Post[] } enum Role { USER ADMIN } //highlight-end ``` ```prisma highlight=10-45;normal datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } //highlight-start model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique name String? role Role @default(USER) posts Post[] profile Profile? } model Profile { id String @id @default(auto()) @map("_id") @db.ObjectId bio String user User @relation(fields: [userId], references: [id]) userId String @unique @db.ObjectId } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId createdAt DateTime @default(now()) title String published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId categoryIDs String[] @db.ObjectId categories Category[] @relation(fields: [categoryIDs], references: [id]) } model Category { id String @id @default(auto()) @map("_id") @db.ObjectId name String postIDs String[] @db.ObjectId posts Post[] @relation(fields: [postIDs], references: [id]) } enum Role { USER //highlight-end ADMIN } ``` The data model definition is made up of: - [Models](#defining-models) ([`model`](/orm/reference/prisma-schema-reference#model) primitives) that define a number of fields, including [relations between models](#relation-fields) - [Enums](#defining-enums) ([`enum`](/orm/reference/prisma-schema-reference#enum) primitives) (if your connector supports Enums) - [Attributes](#defining-attributes) and [functions](#using-functions) that change the behavior of fields and models The corresponding database looks like this: ![Sample database](/img/orm/sample-database.png)
A model maps to the underlying structures of the data source. - In relational databases like PostgreSQL and MySQL, a `model` maps to a **table** - In MongoDB, a `model` maps to a **collection** > **Note**: In the future there might be connectors for non-relational databases and other data sources. For example, for a REST API it would map to a _resource_.
The following query uses Prisma Client that's generated from this data model to create: - A `User` record - Two nested `Post` records - Three nested `Category` records ```ts const user = await prisma.user.create({ data: { email: 'ariadne@prisma.io', name: 'Ariadne', posts: { create: [ { title: 'My first day at Prisma', categories: { create: { name: 'Office', }, }, }, { title: 'How to connect to a SQLite database', categories: { create: [{ name: 'Databases' }, { name: 'Tutorials' }], }, }, ], }, }, }) ``` ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient({}) // A `main` function so that you can use async/await async function main() { // Create user, posts, and categories const user = await prisma.user.create({ data: { email: 'ariadne@prisma.io', name: 'Ariadne', posts: { create: [ { title: 'My first day at Prisma', categories: { create: { name: 'Office', }, }, }, { title: 'How to connect to a SQLite database', categories: { create: [{ name: 'Databases' }, { name: 'Tutorials' }], }, }, ], }, }, }) // Return user, and posts, and categories const returnUser = await prisma.user.findUnique({ where: { id: user.id, }, include: { posts: { include: { categories: true, }, }, }, }) console.log(returnUser) } main() ``` Your data model reflects _your_ application domain. For example: - In an **ecommerce** application you probably have models like `Customer`, `Order`, `Item` and `Invoice`. - In a **social media** application you probably have models like `User`, `Post`, `Photo` and `Message`. ## Introspection and migration There are two ways to define a data model: - **Write the data model manually and use Prisma Migrate**: You can write your data model manually and map it to your database using [Prisma Migrate](/orm/prisma-migrate). In this case, the data model is the single source of truth for the models of your application. - **Generate the data model via introspection**: When you have an existing database or prefer migrating your database schema with SQL, you generate the data model by [introspecting](/orm/prisma-schema/introspection) your database. In this case, the database schema is the single source of truth for the models of your application. ## Defining models Models represent the entities of your application domain. Models are represented by [`model`](/orm/reference/prisma-schema-reference#model) blocks and define a number of [fields](/orm/reference/prisma-schema-reference#model-fields). In the example data model above, `User`, `Profile`, `Post` and `Category` are models. A blogging platform can be extended with the following models: ```prisma model Comment { // Fields } model Tag { // Fields } ``` ### Mapping model names to tables or collections Prisma model [naming conventions (singular form, PascalCase)](/orm/reference/prisma-schema-reference#naming-conventions) do not always match table names in the database. A common approach for naming tables/collections in databases is to use plural form and [snake_case](https://en.wikipedia.org/wiki/Snake_case) notation - for example: `comments`. When you introspect a database with a table named `comments`, the result Prisma model will look like this: ```prisma model comments { // Fields } ``` However, you can still adhere to the naming convention without renaming the underlying `comments` table in the database by using the [`@@map`](/orm/reference/prisma-schema-reference#map-1) attribute: ```prisma model Comment { // Fields @@map("comments") } ``` With this model definition, Prisma ORM automatically maps the `Comment` model to the `comments` table in the underlying database. > **Note**: You can also [`@map`](/orm/reference/prisma-schema-reference#map) a column name or enum value, and `@@map` an enum name. `@map` and `@@map` allow you to [tune the shape of your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names#using-map-and-map-to-rename-fields-and-models-in-the-prisma-client-api) by decoupling model and field names from table and column names in the underlying database.
## Defining fields The properties of a model are called _fields_, which consist of: - A **[field name](/orm/reference/prisma-schema-reference#model-fields)** - A **[field type](/orm/reference/prisma-schema-reference#model-fields)** - Optional **[type modifiers](#type-modifiers)** - Optional **[attributes](#defining-attributes)**, including [native database type attributes](#native-types-mapping) A field's type determines its _structure_, and fits into one of two categories: - [Scalar types](#scalar-fields) (includes [enums](#defining-enums)) that map to columns (relational databases) or document fields (MongoDB) in the database - for example, [`String`](/orm/reference/prisma-schema-reference#string) or [`Int`](/orm/reference/prisma-schema-reference#int) - Model types (the field is then called [relation field](/orm/prisma-schema/data-model/relations#relation-fields)) - for example `Post` or `Comment[]`. The following table describes `User` model's fields from the sample schema:
Expand to see table | Name | Type | Scalar vs Relation | Type modifier | Attributes | | :-------- | :-------- | :---------------------------- | :------------ | :------------------------------------ | | `id` | `Int` | Scalar | - | `@id` and `@default(autoincrement())` | | `email` | `String` | Scalar | - | `@unique` | | `name` | `String` | Scalar | `?` | - | | `role` | `Role` | Scalar (`enum`) | - | `@default(USER)` | | `posts` | `Post` | Relation (Prisma-level field) | `[]` | - | | `profile` | `Profile` | Relation (Prisma-level field) | `?` | - |
### Scalar fields The following example extends the `Comment` and `Tag` models with several scalar types. Some fields include [attributes](#defining-attributes): ```prisma highlight=2-4,8;normal model Comment { //highlight-start id Int @id @default(autoincrement()) title String content String //highlight-end } model Tag { //highlight-next-line name String @id } ``` ```prisma highlight=2-4,8;normal model Comment { //highlight-start id String @id @default(auto()) @map("_id") @db.ObjectId title String content String //highlight-end } model Tag { //highlight-next-line name String @id @map("_id") } ``` See [complete list of scalar field types](/orm/reference/prisma-schema-reference#model-field-scalar-types) . ### Relation fields A relation field's type is another model - for example, a post (`Post`) can have multiple comments (`Comment[]`): ```prisma highlight=4,10;normal model Post { id Int @id @default(autoincrement()) // Other fields //highlight-next-line comments Comment[] // A post can have many comments } model Comment { id Int // Other fields //highlight-next-line post Post? @relation(fields: [postId], references: [id]) // A comment can have one post postId Int? } ``` ```prisma highlight=4,10;normal model Post { id String @id @default(auto()) @map("_id") @db.Objectid // Other fields //highlight-next-line comments Comment[] // A post can have many comments } model Comment { id String @id @default(auto()) @map("_id") @db.Objectid // Other fields //highlight-next-line post Post? @relation(fields: [postId], references: [id]) // A comment can have one post postId String? @db.ObjectId } ``` Refer to the [relations documentation](/orm/prisma-schema/data-model/relations) for more examples and information about relationships between models. ### Native types mapping Version [2.17.0](https://github.com/prisma/prisma/releases/tag/2.17.0) and later support **native database type attributes** (type attributes) that describe the underlying database type: ```prisma highlight=3;normal model Post { id Int @id //highlight-next-line title String @db.VarChar(200) content String } ``` Type attributes are: - Specific to the underlying provider - for example, PostgreSQL uses `@db.Boolean` for `Boolean` whereas MySQL uses `@db.TinyInt(1)` - Written in PascalCase (for example, `VarChar` or `Text`) - Prefixed by `@db`, where `db` is the name of the `datasource` block in your schema Furthermore, during [Introspection](/orm/prisma-schema/introspection) type attributes are _only_ added to the schema if the underlying native type is **not the default type**. For example, if you are using the PostgreSQL provider, `String` fields where the underlying native type is `text` will not have a type attribute. See [complete list of native database type attributes per scalar type and provider](/orm/reference/prisma-schema-reference#model-field-scalar-types) . #### Benefits and workflows - Control **the exact native type** that [Prisma Migrate](/orm/prisma-migrate) creates in the database - for example, a `String` can be `@db.VarChar(200)` or `@db.Char(50)` - See an **enriched schema** when you introspect ### Type modifiers The type of a field can be modified by appending either of two modifiers: - [`[]`](/orm/reference/prisma-schema-reference#-modifier) Make a field a list - [`?`](/orm/reference/prisma-schema-reference#-modifier-1) Make a field optional > **Note**: You **cannot** combine type modifiers - optional lists are not supported. #### Lists The following example includes a scalar list and a list of related models: ```prisma highlight=4,5;normal model Post { id Int @id @default(autoincrement()) // Other fields //highlight-start comments Comment[] // A list of comments keywords String[] // A scalar list //highlight-end } ``` ```prisma highlight=4,5;normal model Post { id String @id @default(auto()) @map("_id") @db.ObjectId // Other fields //highlight-start comments Comment[] // A list of comments keywords String[] // A scalar list //highlight-end } ``` > **Note**: Scalar lists are **only** supported if the database connector supports scalar lists, either natively or at a Prisma ORM level. #### Optional and mandatory fields ```prisma highlight=4;normal model Comment { id Int @id @default(autoincrement()) title String //highlight-next-line content String? } model Tag { name String @id } ``` ```prisma highlight=4;normal model Comment { id String @id @default(auto()) @map("_id") @db.ObjectId title String //highlight-next-line content String? } model Tag { name String @id @map("_id") } ``` When **not** annotating a field with the `?` type modifier, the field will be _required_ on every record of the model. This has effects on two levels: - **Databases** - **Relational databases**: Required fields are represented via `NOT NULL` constraints in the underlying database. - **MongoDB**: Required fields are not a concept on a MongoDB database level. - **Prisma Client**: Prisma Client's generated [TypeScript types](#type-definitions) that represent the models in your application code will also define these fields as required to ensure they always carry values at runtime. > **Note**: The default value of an optional field is `null`. ### Unsupported types When you introspect a relational database, unsupported data types are added as [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) : ```prisma location Unsupported("POLYGON")? ``` The `Unsupported` type allows you to define fields in the Prisma schema for database types that are not yet supported by Prisma ORM. For example, MySQL's `POLYGON` type is not currently supported by Prisma ORM, but can now be added to the Prisma schema using the `Unsupported("POLYGON")` type. Fields of type `Unsupported` do not appear in the generated Prisma Client API, but you can still use Prisma ORM’s [raw database access feature](/orm/prisma-client/using-raw-sql/raw-queries) to query these fields. > **Note**: If a model has **mandatory `Unsupported` fields**, the generated client will not include `create` or `update` methods for that model. > **Note**: The MongoDB connector does not support nor require the `Unsupported` type because it supports all scalar types. ## Defining attributes Attributes modify the behavior of fields or model blocks. The following example includes three field attributes ([`@id`](/orm/reference/prisma-schema-reference#id) , [`@default`](/orm/reference/prisma-schema-reference#default) , and [`@unique`](/orm/reference/prisma-schema-reference#unique) ) and one block attribute ([`@@unique`](/orm/reference/prisma-schema-reference#unique-1)): ```prisma model User { id Int @id @default(autoincrement()) firstName String lastName String email String @unique isAdmin Boolean @default(false) @@unique([firstName, lastName]) } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId firstName String lastName String email String @unique isAdmin Boolean @default(false) @@unique([firstName, lastName]) } ``` Some attributes accept [arguments](/orm/reference/prisma-schema-reference#attribute-argument-types) - for example, `@default` accepts `true` or `false`: ```prisma isAdmin Boolean @default(false) // short form of @default(value: false) ``` See [complete list of field and block attributes](/orm/reference/prisma-schema-reference#attributes) ### Defining an ID field An ID uniquely identifies individual records of a model. A model can only have _one_ ID: - In **relational databases**, the ID can be a single field or based on multiple fields. If a model does not have an `@id` or an `@@id`, you must define a mandatory `@unique` field or `@@unique` block instead. - In **MongoDB**, an ID must be a single field that defines an `@id` attribute and a `@map("_id")` attribute. #### Defining IDs in relational databases In relational databases, an ID can be defined by a single field using the [`@id`](/orm/reference/prisma-schema-reference#id) attribute, or multiple fields using the [`@@id`](/orm/reference/prisma-schema-reference#id-1) attribute. ##### Single field IDs In the following example, the `User` ID is represented by the `id` integer field: ```prisma highlight=2;normal model User { //highlight-next-line id Int @id @default(autoincrement()) email String @unique name String? role Role @default(USER) posts Post[] profile Profile? } ``` ##### Composite IDs In the following example, the `User` ID is represented by a combination of the `firstName` and `lastName` fields: ```prisma highlight=7;normal model User { firstName String lastName String email String @unique isAdmin Boolean @default(false) //highlight-next-line @@id([firstName, lastName]) } ``` By default, the name of this field in Prisma Client queries will be `firstName_lastName`. You can also provide your own name for the composite ID using the [`@@id`](/orm/reference/prisma-schema-reference#id-1) attribute's `name` field: ```prisma highlight=7;normal model User { firstName String lastName String email String @unique isAdmin Boolean @default(false) //highlight-next-line @@id(name: "fullName", fields: [firstName, lastName]) } ``` The `firstName_lastName` field will now be named `fullName` instead. Refer to the documentation on [working with composite IDs](/orm/prisma-client/special-fields-and-types/working-with-composite-ids-and-constraints) to learn how to interact with a composite ID in Prisma Client. ##### `@unique` fields as unique identifiers In the following example, users are uniquely identified by a `@unique` field. Because the `email` field functions as a unique identifier for the model (which is required), it must be mandatory: ```prisma highlight=2;normal model User { //highlight-next-line email String @unique name String? role Role @default(USER) posts Post[] profile Profile? } ``` **Constraint names in relational databases**
You can optionally define a [custom primary key constraint name](/orm/prisma-schema/data-model/database-mapping#constraint-and-index-names) in the underlying database.
#### Defining IDs in MongoDB The MongoDB connector has [specific rules for defining an ID field](/orm/reference/prisma-schema-reference#mongodb) that differs from relational databases. An ID must be defined by a single field using the [`@id`](/orm/reference/prisma-schema-reference#id) attribute and must include `@map("_id")`. In the following example, the `User` ID is represented by the `id` string field that accepts an auto-generated `ObjectId`: ```prisma highlight=2;normal model User { //highlight-next-line id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique name String? role Role @default(USER) posts Post[] profile Profile? } ``` In the following example, the `User` ID is represented by the `id` string field that accepts something other than an `ObjectId` - for example, a unique username: ```prisma highlight=2;normal model User { //highlight-next-line id String @id @map("_id") email String @unique name String? role Role @default(USER) posts Post[] profile Profile? } ``` **MongoDB does not support `@@id`**
MongoDB does not support composite IDs, which means you cannot identify a model with a `@@id` block.
### Defining a default value You can define default values for scalar fields of your models using the [`@default`](/orm/reference/prisma-schema-reference#default) attribute: ```prisma highlight=3,5;normal model Post { id Int @id @default(autoincrement()) //highlight-next-line createdAt DateTime @default(now()) title String //highlight-next-line published Boolean @default(false) //highlight-next-line data Json @default("{ \"hello\": \"world\" }") author User @relation(fields: [authorId], references: [id]) authorId Int categories Category[] @relation(references: [id]) } ``` ```prisma highlight=3,5;normal model Post { id String @id @default(auto()) @map("_id") @db.ObjectId createdAt DateTime @default(now()) title String published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId categories Category[] @relation(references: [id]) } ``` `@default` attributes either: - Represent `DEFAULT` values in the underlying database (relational databases only) _or_ - Use a Prisma ORM-level function. For example, `cuid()` and `uuid()` are provided by Prisma Client's [query engine](/orm/more/under-the-hood/engines) for all connectors. Default values can be: - Static values that correspond to the field type, such as `5` (`Int`), `Hello` (`String`), or `false` (`Boolean`) - [Lists](/orm/reference/prisma-schema-reference#-modifier) of static values, such as `[5, 6, 8]` (`Int[]`) or `["Hello", "Goodbye"]` (`String`[]). These are available in Prisma ORM versions `4.0.0` and later, when using supported databases (PostgreSQL, CockroachDB and MongoDB) - [Functions](#using-functions), such as [`now()`](/orm/reference/prisma-schema-reference#now) or [`uuid()`](/orm/reference/prisma-schema-reference#uuid) - JSON data. Note that JSON needs to be enclosed with double-quotes inside the `@default` attribute, e.g.: `@default("[]")`. If you want to provide a JSON object, you need to enclose it with double-quotes and then escape any internal double quotes using a backslash, e.g.: `@default("{ \"hello\": \"world\" }")`. Refer to the [attribute function reference documentation](/orm/reference/prisma-schema-reference#attribute-functions) for information about connector support for functions. ### Defining a unique field You can add unique attributes to your models to be able to uniquely identify individual records of that model. Unique attributes can be defined on a single field using [`@unique`](/orm/reference/prisma-schema-reference#unique) attribute, or on multiple fields (also called composite or compound unique constraints) using the [`@@unique`](/orm/reference/prisma-schema-reference#unique-1) attribute. In the following example, the value of the `email` field must be unique: ```prisma model User { id Int @id @default(autoincrement()) email String @unique name String? } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique name String? } ``` In the following example, a combination of `authorId` and `title` must be unique: ```prisma highlight=10;normal model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) title String published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int categories Category[] @relation(references: [id]) //highlight-next-line @@unique([authorId, title]) } ``` ```prisma highlight=10;normal model Post { id String @id @default(auto()) @map("_id") @db.ObjectId createdAt DateTime @default(now()) title String published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId categories Category[] @relation(references: [id]) //highlight-next-line @@unique([authorId, title]) } ``` **Constraint names in relational databases**
You can optionally define a [custom unique constraint name](/orm/prisma-schema/data-model/database-mapping#constraint-and-index-names) in the underlying database.
By default, the name of this field in Prisma Client queries will be `authorId_title`. You can also provide your own name for the composite unique constraint using the [`@@unique`](/orm/prisma-schema/data-model/database-mapping#constraint-and-index-names) attribute's `name` field: ```prisma highlight=10;normal model Post { id String @id @default(auto()) @map("_id") @db.ObjectId createdAt DateTime @default(now()) title String published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId categories Category[] @relation(references: [id]) //highlight-next-line @@unique(name: "authorTitle", [authorId, title]) } ``` The `authorId_title` field will now be named `authorTitle` instead. Refer to the documentation on [working with composite unique identifiers](/orm/prisma-client/special-fields-and-types/working-with-composite-ids-and-constraints) to learn how to interact with a composite unique constraints in Prisma Client. #### Composite type unique constraints When using the MongoDB provider in version `3.12.0` and later, you can define a unique constraint on a field of a [composite type](#defining-composite-types) using the syntax `@@unique([compositeType.field])`. As with other fields, composite type fields can be used as part of a multi-column unique constraint. The following example defines a multi-column unique constraint based on the `email` field of the `User` model and the `number` field of the `Address` composite type which is used in `User.address`: ```prisma file=schema.prisma showLineNumbers type Address { street String number Int } model User { id Int @id email String address Address @@unique([email, address.number]) } ``` This notation can be chained if there is more than one nested composite type: ```prisma file=schema.prisma showLineNumbers type City { name String } type Address { number Int city City } model User { id Int @id address Address[] @@unique([address.city.name]) } ``` ### Defining an index You can define indexes on one or multiple fields of your models via the [`@@index`](/orm/reference/prisma-schema-reference#index) on a model. The following example defines a multi-column index based on the `title` and `content` field: ```prisma model Post { id Int @id @default(autoincrement()) title String content String? @@index([title, content]) } ``` **Index names in relational databases**
You can optionally define a [custom index name](/orm/prisma-schema/data-model/database-mapping#constraint-and-index-names) in the underlying database.
#### Defining composite type indexes When using the MongoDB provider in version `3.12.0` and later, you can define an index on a field of a [composite type](#defining-composite-types) using the syntax `@@index([compositeType.field])`. As with other fields, composite type fields can be used as part of a multi-column index. The following example defines a multi-column index based on the `email` field of the `User` model and the `number` field of the `Address` composite type: ```prisma file=schema.prisma showLineNumbers type Address { street String number Int } model User { id Int @id email String address Address @@index([email, address.number]) } ``` This notation can be chained if there is more than one nested composite type: ```prisma file=schema.prisma showLineNumbers type City { name String } type Address { number Int city City } model User { id Int @id address Address[] @@index([address.city.name]) } ``` ## Defining enums You can define enums in your data model [if enums are supported for your database connector](/orm/reference/database-features#misc), either natively or at Prisma ORM level. Enums are considered [scalar](#scalar-fields) types in the Prisma schema data model. They're therefore [by default](/orm/prisma-client/queries/select-fields#return-the-default-fields) included as return values in [Prisma Client queries](/orm/prisma-client/queries/crud). Enums are defined via the [`enum`](/orm/reference/prisma-schema-reference#enum) block. For example, a `User` has a `Role`: ```prisma highlight=5,8-11;normal model User { id Int @id @default(autoincrement()) email String @unique name String? //highlight-next-line role Role @default(USER) } //highlight-start enum Role { USER ADMIN } //highlight-end ``` ```prisma highlight=5,8-11;normal model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique name String? //highlight-next-line role Role @default(USER) } //highlight-start enum Role { USER ADMIN } //highlight-end ``` ## Defining composite types Composite types were added in version `3.10.0` under the `mongodb` Preview feature flag and are in General Availability since version `3.12.0`. Composite types are currently only available on MongoDB. Composite types (known as [embedded documents](https://www.mongodb.com/docs/manual/data-modeling/#embedded-data) in MongoDB) provide support for embedding records inside other records, by allowing you to define new object types. Composite types are structured and typed in a similar way to [models](#defining-models). To define a composite type, use the `type` block. As an example, take the following schema: ```prisma file=schema.prisma showLineNumbers model Product { id String @id @default(auto()) @map("_id") @db.ObjectId name String photos Photo[] } type Photo { height Int width Int url String } ``` In this case, the `Product` model has a list of `Photo` composite types stored in `photos`. ### Considerations when using composite types Composite types only support a limited set of [attributes](/orm/reference/prisma-schema-reference#attributes). The following attributes are supported: - `@default` - `@map` - [Native types](/orm/reference/prisma-schema-reference#model-field-scalar-types), such as `@db.ObjectId` The following attributes are not supported inside composite types: - `@unique` - `@id` - `@relation` - `@ignore` - `@updatedAt` However, unique constraints can still be defined by using the `@@unique` attribute on the level of the model that uses the composite type. For more details, see [Composite type unique constraints](#composite-type-unique-constraints). Indexes can be defined by using the `@@index` attribute on the level of the model that uses the composite type. For more details, see [Composite type indexes](#defining-composite-type-indexes). ## Using functions The Prisma schema supports a number of [functions](/orm/reference/prisma-schema-reference#attribute-functions) . These can be used to specify [default values](/orm/reference/prisma-schema-reference#default) on fields of a model. For example, the default value of `createdAt` is [`now()`](/orm/reference/prisma-schema-reference#now) : ```prisma model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) } ``` ```prisma model Post { id String @default(auto()) @map("_id") @db.ObjectId createdAt DateTime @default(now()) } ``` [`cuid()`](/orm/reference/prisma-schema-reference#cuid) and [`uuid()`](/orm/reference/prisma-schema-reference#uuid) are implemented by Prisma ORM and therefore are not "visible" in the underlying database schema. You can still use them when using [introspection](/orm/prisma-schema/introspection) by [manually changing your Prisma schema](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) and [generating Prisma Client](/orm/prisma-client/setup-and-configuration/generating-prisma-client), in that case the values will be generated by Prisma Client's [query engine](/orm/more/under-the-hood/engines) Support for [`autoincrement()`](/orm/reference/prisma-schema-reference#autoincrement), [`now()`](/orm/reference/prisma-schema-reference#now), and [`dbgenerated(...)`](/orm/reference/prisma-schema-reference#dbgenerated) differ between databases. **Relational database connectors** implement `autoincrement()`, `dbgenerated(...)`, and `now()` at database level. The **MongoDB connector** does not support `autoincrement()` or `dbgenerated(...)`, and `now()` is implemented at the Prisma ORM level. The [`auto()`](/orm/reference/prisma-schema-reference#auto) function is used to generate an `ObjectId`. ## Relations Refer to the [relations documentation](/orm/prisma-schema/data-model/relations) for more examples and information about relationships between models. ## Models in Prisma Client ### Queries (CRUD) Every model in the data model definition will result in a number of CRUD queries in the generated [Prisma Client API](/orm/prisma-client): - [`findMany()`](/orm/reference/prisma-client-reference#findmany) - [`findFirst()`](/orm/reference/prisma-client-reference#findfirst) - [`findFirstOrThrow()`](/orm/reference/prisma-client-reference#findfirstorthrow) - [`findUnique()`](/orm/reference/prisma-client-reference#findunique) - [`findUniqueOrThrow()`](/orm/reference/prisma-client-reference#finduniqueorthrow) - [`create()`](/orm/reference/prisma-client-reference#create) - [`update()`](/orm/reference/prisma-client-reference#update) - [`upsert()`](/orm/reference/prisma-client-reference#upsert) - [`delete()`](/orm/reference/prisma-client-reference#delete) - [`createMany()`](/orm/reference/prisma-client-reference#createmany) - [`createManyAndReturn()`](/orm/reference/prisma-client-reference#createmanyandreturn) - [`updateMany()`](/orm/reference/prisma-client-reference#updatemany) - [`updateManyAndReturn()`](/orm/reference/prisma-client-reference#updatemanyandreturn) - [`deleteMany()`](/orm/reference/prisma-client-reference#deletemany) The operations are accessible via a generated property on the Prisma Client instance. By default the name of the property is the lowercase form of the model name, e.g. `user` for a `User` model or `post` for a `Post` model. Here is an example illustrating the use of a `user` property from the Prisma Client API: ```js const newUser = await prisma.user.create({ data: { name: 'Alice', }, }) const allUsers = await prisma.user.findMany() ``` ### Type definitions Prisma Client also generates **type definitions** that reflect your model structures. These are part of the generated [`@prisma/client`](/orm/prisma-client/setup-and-configuration/generating-prisma-client#the-prismaclient-npm-package) node module. When using TypeScript, these type definitions ensure that all your database queries are entirely type safe and validated at compile-time (even partial queries using [`select`](/orm/reference/prisma-client-reference#select) or [`include`](/orm/reference/prisma-client-reference#include) ). Even when using plain JavaScript, the type definitions are still included in the `@prisma/client` node module, enabling features like [IntelliSense](https://code.visualstudio.com/docs/editor/intellisense)/autocompletion in your editor. > **Note**: The actual types are stored in the `.prisma/client` folder. `@prisma/client/index.d.ts` exports the contents of this folder. For example, the type definition for the `User` model from above would look as follows: ```ts export type User = { id: number email: string name: string | null role: string } ``` Note that the relation fields `posts` and `profile` are not included in the type definition by default. However, if you need variations of the `User` type you can still define them using some of [Prisma Client's generated helper types](/orm/prisma-client/setup-and-configuration/generating-prisma-client) (in this case, these helper types would be called `UserGetIncludePayload` and `UserGetSelectPayload`). ## Limitations ### Records must be uniquely identifiable Prisma ORM currently only supports models that have at least one unique field or combination of fields. In practice, this means that every Prisma model must have either at least one of the following attributes: - `@id` or `@@id` for a single- or multi-field primary key constraint (max one per model) - `@unique` or `@@unique` for a single- or multi-field unique constraint --- # One-to-one relations URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/one-to-one-relations This page introduces one-to-one relations and explains how to use them in your Prisma schema. ## Overview One-to-one (1-1) relations refer to relations where at most **one** record can be connected on both sides of the relation. In the example below, there is a one-to-one relation between `User` and `Profile`: ```prisma model User { id Int @id @default(autoincrement()) profile Profile? } model Profile { id Int @id @default(autoincrement()) user User @relation(fields: [userId], references: [id]) userId Int @unique // relation scalar field (used in the `@relation` attribute above) } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId profile Profile? } model Profile { id String @id @default(auto()) @map("_id") @db.ObjectId user User @relation(fields: [userId], references: [id]) userId String @unique @db.ObjectId // relation scalar field (used in the `@relation` attribute above) } ``` The `userId` relation scalar is a direct representation of the foreign key in the underlying database. This one-to-one relation expresses the following: - "a user can have zero profiles or one profile" (because the `profile` field is [optional](/orm/prisma-schema/data-model/models#type-modifiers) on `User`) - "a profile must always be connected to one user" In the previous example, the `user` relation field of the `Profile` model references the `id` field of the `User` model. You can also reference a different field. In this case, you need to mark the field with the `@unique` attribute, to guarantee that there is only a single `User` connected to each `Profile`. In the following example, the `user` field references an `email` field in the `User` model, which is marked with the `@unique` attribute: ```prisma model User { id Int @id @default(autoincrement()) email String @unique // <-- add unique attribute profile Profile? } model Profile { id Int @id @default(autoincrement()) user User @relation(fields: [userEmail], references: [email]) userEmail String @unique // relation scalar field (used in the `@relation` attribute above) } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique // <-- add unique attribute profile Profile? } model Profile { id String @id @default(auto()) @map("_id") @db.ObjectId user User @relation(fields: [userEmail], references: [email]) userEmail String @unique @db.ObjectId // relation scalar field (used in the `@relation` attribute above) } ``` In MySQL, you can create a foreign key with only an index on the referenced side, and not a unique constraint. In Prisma ORM versions 4.0.0 and later, if you introspect a relation of this type it will trigger a validation error. To fix this, you will need to add a `@unique` constraint to the referenced field. ## Multi-field relations in relational databases In **relational databases only**, you can also use [multi-field IDs](/orm/reference/prisma-schema-reference#id-1) to define a 1-1 relation: ```prisma model User { firstName String lastName String profile Profile? @@id([firstName, lastName]) } model Profile { id Int @id @default(autoincrement()) user User @relation(fields: [userFirstName, userLastName], references: [firstName, lastName]) userFirstName String // relation scalar field (used in the `@relation` attribute above) userLastName String // relation scalar field (used in the `@relation` attribute above) @@unique([userFirstName, userLastName]) } ``` ## 1-1 relations in the database ### Relational databases The following example demonstrates how to create a 1-1 relation in SQL: ```sql CREATE TABLE "User" ( id SERIAL PRIMARY KEY ); CREATE TABLE "Profile" ( id SERIAL PRIMARY KEY, "userId" INTEGER NOT NULL UNIQUE, FOREIGN KEY ("userId") REFERENCES "User"(id) ); ``` Notice that there is a `UNIQUE` constraint on the foreign key `userId`. If this `UNIQUE` constraint was missing, the relation would be considered a [1-n relation](/orm/prisma-schema/data-model/relations/one-to-many-relations). The following example demonstrates how to create a 1-1 relation in SQL using a composite key (`firstName` and `lastName`): ```sql CREATE TABLE "User" ( firstName TEXT, lastName TEXT, PRIMARY KEY ("firstName","lastName") ); CREATE TABLE "Profile" ( id SERIAL PRIMARY KEY, "userFirstName" TEXT NOT NULL, "userLastName" TEXT NOT NULL, UNIQUE ("userFirstName", "userLastName") FOREIGN KEY ("userFirstName", "userLastName") REFERENCES "User"("firstName", "lastName") ); ``` ### MongoDB For MongoDB, Prisma ORM currently uses a [normalized data model design](https://www.mongodb.com/docs/manual/data-modeling/), which means that documents reference each other by ID in a similar way to relational databases. The following MongoDB document represents a `User`: ```json { "_id": { "$oid": "60d58e130011041800d209e1" }, "name": "Bob" } ``` The following MongoDB document represents a `Profile` - notice the `userId` field, which references the `User` document's `$oid`: ```json { "_id": { "$oid": "60d58e140011041800d209e2" }, "bio": "I'm Bob, and I like drawing.", "userId": { "$oid": "60d58e130011041800d209e1" } } ``` ## Required and optional 1-1 relation fields In a one-to-one relation, the side of the relation _without_ a relation scalar (the field representing the foreign key in the database) _must_ be optional: ```prisma highlight=3;normal model User { id Int @id @default(autoincrement()) //highlight-next-line profile Profile? // No relation scalar - must be optional } ``` This restriction was introduced in 2.12.0. However, you can choose if the side of the relation _with_ a relation scalar should be optional or mandatory. ### Mandatory 1-1 relation In the following example, `profile` and `profileId` are mandatory. This means that you cannot create a `User` without connecting or creating a `Profile`: ```prisma model User { id Int @id @default(autoincrement()) profile Profile @relation(fields: [profileId], references: [id]) // references `id` of `Profile` profileId Int @unique // relation scalar field (used in the `@relation` attribute above) } model Profile { id Int @id @default(autoincrement()) user User? } ``` ### Optional 1-1 relation In the following example, `profile` and `profileId` are optional. This means that you can create a user without connecting or creating a `Profile`: ```prisma model User { id Int @id @default(autoincrement()) profile Profile? @relation(fields: [profileId], references: [id]) // references `id` of `Profile` profileId Int? @unique // relation scalar field (used in the `@relation` attribute above) } model Profile { id Int @id @default(autoincrement()) user User? } ``` ## Choosing which side should store the foreign key in a 1-1 relation In **1-1 relations**, you can decide yourself which side of the relation you want to annotate with the `@relation` attribute (and therefore holds the foreign key). In the following example, the relation field on the `Profile` model is annotated with the `@relation` attribute. `userId` is a direct representation of the foreign key in the underlying database: ```prisma model User { id Int @id @default(autoincrement()) profile Profile? } model Profile { id Int @id @default(autoincrement()) user User @relation(fields: [userId], references: [id]) userId Int @unique // relation scalar field (used in the `@relation` attribute above) } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId profile Profile? } model Profile { id String @id @default(auto()) @map("_id") @db.ObjectId user User @relation(fields: [userId], references: [id]) userId String @unique @db.ObjectId } ``` You can also annotate the other side of the relation with the `@relation` attribute. The following example annotates the relation field on the `User` model. `profileId` is a direct representation of the foreign key in the underlying database: ```prisma model User { id Int @id @default(autoincrement()) profile Profile? @relation(fields: [profileId], references: [id]) profileId Int? @unique // relation scalar field (used in the `@relation` attribute above) } model Profile { id Int @id @default(autoincrement()) user User? } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId profile Profile? @relation(fields: [profileId], references: [id]) profileId String? @unique @db.ObjectId // relation scalar field (used in the `@relation` attribute above) } model Profile { id String @id @default(auto()) @map("_id") @db.ObjectId user User? } ``` --- # One-to-many relations URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/one-to-many-relations This page introduces one-to-many relations and explains how to use them in your Prisma schema. ## Overview One-to-many (1-n) relations refer to relations where one record on one side of the relation can be connected to zero or more records on the other side. In the following example, there is one one-to-many relation between the `User` and `Post` models: ```prisma model User { id Int @id @default(autoincrement()) posts Post[] } model Post { id Int @id @default(autoincrement()) author User @relation(fields: [authorId], references: [id]) authorId Int } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId posts Post[] } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId } ``` > **Note** The `posts` field does not "manifest" in the underlying database schema. On the other side of the relation, the [annotated relation field](/orm/prisma-schema/data-model/relations#relation-fields) `author` and its relation scalar `authorId` represent the side of the relation that stores the foreign key in the underlying database. This one-to-many relation expresses the following: - "a user can have zero or more posts" - "a post must always have an author" In the previous example, the `author` relation field of the `Post` model references the `id` field of the `User` model. You can also reference a different field. In this case, you need to mark the field with the `@unique` attribute, to guarantee that there is only a single `User` connected to each `Post`. In the following example, the `author` field references an `email` field in the `User` model, which is marked with the `@unique` attribute: ```prisma model User { id Int @id @default(autoincrement()) email String @unique // <-- add unique attribute posts Post[] } model Post { id Int @id @default(autoincrement()) authorEmail String author User @relation(fields: [authorEmail], references: [email]) } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique // <-- add unique attribute posts Post[] } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId authorEmail String author User @relation(fields: [authorEmail], references: [email]) } ``` In MySQL, you can create a foreign key with only an index on the referenced side, and not a unique constraint. In Prisma ORM versions 4.0.0 and later, if you introspect a relation of this type it will trigger a validation error. To fix this, you will need to add a `@unique` constraint to the referenced field. ## Multi-field relations in relational databases In **relational databases only**, you can also define this relation using [multi-field IDs](/orm/reference/prisma-schema-reference#id-1)/composite key: ```prisma model User { firstName String lastName String post Post[] @@id([firstName, lastName]) } model Post { id Int @id @default(autoincrement()) author User @relation(fields: [authorFirstName, authorLastName], references: [firstName, lastName]) authorFirstName String // relation scalar field (used in the `@relation` attribute above) authorLastName String // relation scalar field (used in the `@relation` attribute above) } ``` ## 1-n relations in the database ### Relational databases The following example demonstrates how to create a 1-n relation in SQL: ```sql CREATE TABLE "User" ( id SERIAL PRIMARY KEY ); CREATE TABLE "Post" ( id SERIAL PRIMARY KEY, "authorId" integer NOT NULL, FOREIGN KEY ("authorId") REFERENCES "User"(id) ); ``` Since there's no `UNIQUE` constraint on the `authorId` column (the foreign key), you can create **multiple `Post` records that point to the same `User` record**. This makes the relation a one-to-many rather than a one-to-one. The following example demonstrates how to create a 1-n relation in SQL using a composite key (`firstName` and `lastName`): ```sql CREATE TABLE "User" ( firstName TEXT, lastName TEXT, PRIMARY KEY ("firstName","lastName") ); CREATE TABLE "Post" ( id SERIAL PRIMARY KEY, "authorFirstName" TEXT NOT NULL, "authorLastName" TEXT NOT NULL, FOREIGN KEY ("authorFirstName", "authorLastName") REFERENCES "User"("firstName", "lastName") ); ``` #### Comparing one-to-one and one-to-many relations In relational databases, the main difference between a 1-1 and a 1-n-relation is that in a 1-1-relation the foreign key must have a `UNIQUE` constraint defined on it. ### MongoDB For MongoDB, Prisma ORM currently uses a [normalized data model design](https://www.mongodb.com/docs/manual/data-modeling/), which means that documents reference each other by ID in a similar way to relational databases. The following MongoDB document represents a `User`: ```json { "_id": { "$oid": "60d5922d00581b8f0062e3a8" }, "name": "Ella" } ``` Each of the following `Post` MongoDB documents has an `authorId` field which references the same user: ```json [ { "_id": { "$oid": "60d5922e00581b8f0062e3a9" }, "title": "How to make sushi", "authorId": { "$oid": "60d5922d00581b8f0062e3a8" } }, { "_id": { "$oid": "60d5922e00581b8f0062e3aa" }, "title": "How to re-install Windows", "authorId": { "$oid": "60d5922d00581b8f0062e3a8" } } ] ``` #### Comparing one-to-one and one-to-many relations In MongoDB, the only difference between a 1-1 and a 1-n is the number of documents referencing another document in the database - there are no constraints. ## Required and optional relation fields in one-to-many relations A 1-n-relation always has two relation fields: - a [list](/orm/prisma-schema/data-model/models#type-modifiers) relation field which is _not_ annotated with `@relation` - the [annotated relation field](/orm/prisma-schema/data-model/relations#annotated-relation-fields) (including its relation scalar) The annotated relation field and relation scalar of a 1-n relation can either _both_ be optional, or _both_ be mandatory. On the other side of the relation, the list is **always mandatory**. ### Optional one-to-many relation In the following example, you can create a `Post` without assigning a `User`: ```prisma model User { id Int @id @default(autoincrement()) posts Post[] } model Post { id Int @id @default(autoincrement()) author User? @relation(fields: [authorId], references: [id]) authorId Int? } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId posts Post[] } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId author User? @relation(fields: [authorId], references: [id]) authorId String? @db.ObjectId } ``` ### Mandatory one-to-many relation In the following example, you must assign a `User` when you create a `Post`: ```prisma model User { id Int @id @default(autoincrement()) posts Post[] } model Post { id Int @id @default(autoincrement()) author User @relation(fields: [authorId], references: [id]) authorId Int } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId posts Post[] } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId } ``` --- # Many-to-many relations URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/many-to-many-relations Many-to-many (m-n) relations refer to relations where zero or more records on one side of the relation can be connected to zero or more records on the other side. Prisma schema syntax and the implementation in the underlying database differs between [relational databases](#relational-databases) and [MongoDB](#mongodb). ## Relational databases In relational databases, m-n-relations are typically modelled via [relation tables](/orm/prisma-schema/data-model/relations/many-to-many-relations#relation-tables). m-n-relations can be either [explicit](#explicit-many-to-many-relations) or [implicit](#implicit-many-to-many-relations) in the Prisma schema. We recommend using [implicit](#implicit-many-to-many-relations) m-n-relations if you do not need to store any additional meta-data in the relation table itself. You can always migrate to an [explicit](#explicit-many-to-many-relations) m-n-relation later if needed. ### Explicit many-to-many relations In an explicit m-n relation, the **relation table is represented as a model in the Prisma schema** and can be used in queries. Explicit m-n relations define three models: - Two models with m-n relation, such as `Category` and `Post`. - One model that represents the [relation table](#relation-tables), such as `CategoriesOnPosts` (also sometimes called _JOIN_, _link_ or _pivot_ table) in the underlying database. The fields of a relation table model are both annotated relation fields (`post` and `category`) with a corresponding relation scalar field (`postId` and `categoryId`). The relation table `CategoriesOnPosts` connects related `Post` and `Category` records. In this example, the model representing the relation table also **defines additional fields** that describe the `Post`/`Category` relationship - who assigned the category (`assignedBy`), and when the category was assigned (`assignedAt`): ```prisma model Post { id Int @id @default(autoincrement()) title String categories CategoriesOnPosts[] } model Category { id Int @id @default(autoincrement()) name String posts CategoriesOnPosts[] } model CategoriesOnPosts { post Post @relation(fields: [postId], references: [id]) postId Int // relation scalar field (used in the `@relation` attribute above) category Category @relation(fields: [categoryId], references: [id]) categoryId Int // relation scalar field (used in the `@relation` attribute above) assignedAt DateTime @default(now()) assignedBy String @@id([postId, categoryId]) } ``` The underlying SQL looks like this: ```sql CREATE TABLE "Post" ( "id" SERIAL NOT NULL, "title" TEXT NOT NULL, CONSTRAINT "Post_pkey" PRIMARY KEY ("id") ); CREATE TABLE "Category" ( "id" SERIAL NOT NULL, "name" TEXT NOT NULL, CONSTRAINT "Category_pkey" PRIMARY KEY ("id") ); -- Relation table + indexes -- CREATE TABLE "CategoriesOnPosts" ( "postId" INTEGER NOT NULL, "categoryId" INTEGER NOT NULL, "assignedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, CONSTRAINT "CategoriesOnPosts_pkey" PRIMARY KEY ("postId","categoryId") ); ALTER TABLE "CategoriesOnPosts" ADD CONSTRAINT "CategoriesOnPosts_postId_fkey" FOREIGN KEY ("postId") REFERENCES "Post"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ALTER TABLE "CategoriesOnPosts" ADD CONSTRAINT "CategoriesOnPosts_categoryId_fkey" FOREIGN KEY ("categoryId") REFERENCES "Category"("id") ON DELETE RESTRICT ON UPDATE CASCADE; ``` Note that the same rules as for [1-n relations](/orm/prisma-schema/data-model/relations/one-to-many-relations) apply (because `Post`↔ `CategoriesOnPosts` and `Category` ↔ `CategoriesOnPosts` are both in fact 1-n relations), which means one side of the relation needs to be annotated with the `@relation` attribute. When you don't need to attach additional information to the relation, you can model m-n-relations as [implicit m-n-relations](#implicit-many-to-many-relations). If you're not using Prisma Migrate but obtain your data model from [introspection](/orm/prisma-schema/introspection), you can still make use of implicit m-n-relations by following Prisma ORM's [conventions for relation tables](#conventions-for-relation-tables-in-implicit-m-n-relations). #### Querying an explicit many-to-many The following section demonstrates how to query an explicit m-n-relation. You can query the relation model directly (`prisma.categoriesOnPosts(...)`), or use nested queries to go from `Post` -> `CategoriesOnPosts` -> `Category` or the other way. The following query does three things: 1. Creates a `Post` 2. Creates a new record in the relation table `CategoriesOnPosts` 3. Creates a new `Category` that is associated with the newly created `Post` record ```ts const createCategory = await prisma.post.create({ data: { title: 'How to be Bob', categories: { create: [ { assignedBy: 'Bob', assignedAt: new Date(), category: { create: { name: 'New category', }, }, }, ], }, }, }) ``` The following query: - Creates a new `Post` - Creates a new record in the relation table `CategoriesOnPosts` - Connects the category assignment to existing categories (with IDs `9` and `22`) ```ts const assignCategories = await prisma.post.create({ data: { title: 'How to be Bob', categories: { create: [ { assignedBy: 'Bob', assignedAt: new Date(), category: { connect: { id: 9, }, }, }, { assignedBy: 'Bob', assignedAt: new Date(), category: { connect: { id: 22, }, }, }, ], }, }, }) ``` Sometimes you might not know if a `Category` record exists. If the `Category` record exists, you want to connect a new `Post` record to that category. If the `Category` record does not exist, you want to create the record first and then connect it to the new `Post` record. The following query: 1. Creates a new `Post` 2. Creates a new record in the relation table `CategoriesOnPosts` 3. Connects the category assignment to an existing category (with ID `9`), or creates a new category first if it does not exist ```ts const assignCategories = await prisma.post.create({ data: { title: 'How to be Bob', categories: { create: [ { assignedBy: 'Bob', assignedAt: new Date(), category: { connectOrCreate: { where: { id: 9, }, create: { name: 'New Category', id: 9, }, }, }, }, ], }, }, }) ``` The following query returns all `Post` records where at least one (`some`) category assignment (`categories`) refers to a category named `"New category"`: ```ts const getPosts = await prisma.post.findMany({ where: { categories: { some: { category: { name: 'New Category', }, }, }, }, }) ``` The following query returns all categories where at least one (`some`) related `Post` record titles contain the words `"Cool stuff"` _and_ the category was assigned by Bob. ```ts const getAssignments = await prisma.category.findMany({ where: { posts: { some: { assignedBy: 'Bob', post: { title: { contains: 'Cool stuff', }, }, }, }, }, }) ``` The following query gets all category assignments (`CategoriesOnPosts`) records that were assigned by `"Bob"` to one of 5 posts: ```ts const getAssignments = await prisma.categoriesOnPosts.findMany({ where: { assignedBy: 'Bob', post: { id: { in: [9, 4, 10, 12, 22], }, }, }, }) ``` ### Implicit many-to-many relations Implicit m-n relations define relation fields as lists on both sides of the relation. Although the relation table exists in the underlying database, **it is managed by Prisma ORM and does not manifest in the Prisma schema**. Implicit relation tables follow a [specific convention](#conventions-for-relation-tables-in-implicit-m-n-relations). Implicit m-n-relations makes the [Prisma Client API](/orm/prisma-client) for m-n-relations a bit simpler (since you have one fewer level of nesting inside of [nested writes](/orm/prisma-client/queries/relation-queries#nested-writes)). In the example below, there's one _implicit_ m-n-relation between `Post` and `Category`: ```prisma model Post { id Int @id @default(autoincrement()) title String categories Category[] } model Category { id Int @id @default(autoincrement()) name String posts Post[] } ``` ```prisma model Post { id String @id @default(auto()) @map("_id") @db.ObjectId categoryIDs String[] @db.ObjectId categories Category[] @relation(fields: [categoryIDs], references: [id]) } model Category { id String @id @default(auto()) @map("_id") @db.ObjectId name String postIDs String[] @db.ObjectId posts Post[] @relation(fields: [postIDs], references: [id]) } ``` #### Querying an implicit many-to-many The following section demonstrates how to query an [implicit m-n](#implicit-many-to-many-relations) relation. The queries require less nesting than [explicit m-n queries](#querying-an-explicit-many-to-many). The following query creates a single `Post` and multiple `Category` records: ```ts const createPostAndCategory = await prisma.post.create({ data: { title: 'How to become a butterfly', categories: { create: [{ name: 'Magic' }, { name: 'Butterflies' }], }, }, }) ``` The following query creates a single `Category` and multiple `Post` records: ```ts const createCategoryAndPosts = await prisma.category.create({ data: { name: 'Stories', posts: { create: [ { title: 'That one time with the stuff' }, { title: 'The story of planet Earth' }, ], }, }, }) ``` The following query returns all `Post` records with a list of that post's assigned categories: ```ts const getPostsAndCategories = await prisma.post.findMany({ include: { categories: true, }, }) ``` #### Rules for defining an implicit m-n relation Implicit m-n relations: - Use a specific [convention for relation tables](#conventions-for-relation-tables-in-implicit-m-n-relations) - Do **not** require the `@relation` attribute unless you need to [disambiguate relations](/orm/prisma-schema/data-model/relations#disambiguating-relations) with a name, e.g. `@relation("MyRelation")` or `@relation(name: "MyRelation")`. - If you do use the `@relation` attribute, you cannot use the `references`, `fields`, `onUpdate` or `onDelete` arguments. This is because these take a fixed value for implicit m-n-relations and cannot be changed. - Require both models to have a single `@id`. Be aware that: - You cannot use a [multi-field ID](/orm/reference/prisma-schema-reference#id-1) - You cannot use a `@unique` in place of an `@id` To use either of these features, you must use an [explicit m-n instead](#explicit-many-to-many-relations). #### Conventions for relation tables in implicit m-n relations If you obtain your data model from [introspection](/orm/prisma-schema/introspection), you can still use implicit m-n-relations by following Prisma ORM's [conventions for relation tables](#conventions-for-relation-tables-in-implicit-m-n-relations). The following example assumes you want to create a relation table to get an implicit m-n-relation for two models called `Post` and `Category`. ##### Relation table If you want a relation table to be picked up by introspection as an implicit m-n-relation, the name must follow this exact structure: - It must start with an underscore `_` - Then the name of the first model in alphabetical order (in this case `Category`) - Then the relationship (in this case `To`) - Then the name of the second model in alphabetical order (in this case `Post`) In the example, the correct table name is `_CategoryToPost`. When creating an implicit m-n-relation yourself in the Prisma schema file, you can [configure the relation](#configuring-the-name-of-the-relation-table-in-implicit-many-to-many-relations) to have a different name. This will change the name given to the relation table in the database. For example, for a relation named `"MyRelation"` the corresponding table will be called `_MyRelation`. ###### Multi-schema If your implicit many-to-many relationship spans multiple database schemas (using the [`multiSchema` preview feature](/orm/prisma-schema/data-model/multi-schema)), the relation table (with the name defined directly above, in the example `_CategoryToPost`) must be present in the same database schema as the first model in alphabetical order (in this case `Category`). ##### Columns A relation table for an implicit m-n-relation must have exactly two columns: - A foreign key column that points to `Category` called `A` - A foreign key column that points to `Post` called `B` The columns must be called `A` and `B` where `A` points to the model that comes first in the alphabet and `B` points to the model which comes last in the alphabet. ##### Indexes There further must be: - A unique index defined on both foreign key columns: ```sql CREATE UNIQUE INDEX "_CategoryToPost_AB_unique" ON "_CategoryToPost"("A" int4_ops,"B" int4_ops); ``` - A non-unique index defined on B: ```sql CREATE INDEX "_CategoryToPost_B_index" ON "_CategoryToPost"("B" int4_ops); ``` ##### Example This is a sample SQL statement that would create the three tables including indexes (in PostgreSQL dialect) that are picked up as a implicit m-n-relation by Prisma Introspection: ```sql CREATE TABLE "_CategoryToPost" ( "A" integer NOT NULL REFERENCES "Category"(id) , "B" integer NOT NULL REFERENCES "Post"(id) ); CREATE UNIQUE INDEX "_CategoryToPost_AB_unique" ON "_CategoryToPost"("A" int4_ops,"B" int4_ops); CREATE INDEX "_CategoryToPost_B_index" ON "_CategoryToPost"("B" int4_ops); CREATE TABLE "Category" ( id integer SERIAL PRIMARY KEY ); CREATE TABLE "Post" ( id integer SERIAL PRIMARY KEY ); ``` And you can define multiple many-to-many relations between two tables by using the different relationship name. This example shows how the Prisma introspection works under such case: ```sql CREATE TABLE IF NOT EXISTS "User" ( "id" SERIAL PRIMARY KEY ); CREATE TABLE IF NOT EXISTS "Video" ( "id" SERIAL PRIMARY KEY ); CREATE TABLE IF NOT EXISTS "_UserLikedVideos" ( "A" SERIAL NOT NULL, "B" SERIAL NOT NULL, CONSTRAINT "_UserLikedVideos_A_fkey" FOREIGN KEY ("A") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "_UserLikedVideos_B_fkey" FOREIGN KEY ("B") REFERENCES "Video" ("id") ON DELETE CASCADE ON UPDATE CASCADE ); CREATE TABLE IF NOT EXISTS "_UserDislikedVideos" ( "A" SERIAL NOT NULL, "B" SERIAL NOT NULL, CONSTRAINT "_UserDislikedVideos_A_fkey" FOREIGN KEY ("A") REFERENCES "User" ("id") ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT "_UserDislikedVideos_B_fkey" FOREIGN KEY ("B") REFERENCES "Video" ("id") ON DELETE CASCADE ON UPDATE CASCADE ); CREATE UNIQUE INDEX "_UserLikedVideos_AB_unique" ON "_UserLikedVideos"("A", "B"); CREATE INDEX "_UserLikedVideos_B_index" ON "_UserLikedVideos"("B"); CREATE UNIQUE INDEX "_UserDislikedVideos_AB_unique" ON "_UserDislikedVideos"("A", "B"); CREATE INDEX "_UserDislikedVideos_B_index" ON "_UserDislikedVideos"("B"); ``` If you run `prisma db pull` on this database, the Prisma CLI will generate the following schema through introspection: ```prisma model User { id Int @id @default(autoincrement()) Video_UserDislikedVideos Video[] @relation("UserDislikedVideos") Video_UserLikedVideos Video[] @relation("UserLikedVideos") } model Video { id Int @id @default(autoincrement()) User_UserDislikedVideos User[] @relation("UserDislikedVideos") User_UserLikedVideos User[] @relation("UserLikedVideos") } ``` #### Configuring the name of the relation table in implicit many-to-many relations When using Prisma Migrate, you can configure the name of the relation table that's managed by Prisma ORM using the `@relation` attribute. For example, if you want the relation table to be called `_MyRelationTable` instead of the default name `_CategoryToPost`, you can specify it as follows: ```prisma model Post { id Int @id @default(autoincrement()) categories Category[] @relation("MyRelationTable") } model Category { id Int @id @default(autoincrement()) posts Post[] @relation("MyRelationTable") } ``` ### Relation tables A relation table (also sometimes called a _JOIN_, _link_ or _pivot_ table) connects two or more other tables and therefore creates a _relation_ between them. Creating relation tables is a common data modelling practice in SQL to represent relationships between different entities. In essence it means that "one m-n relation is modeled as two 1-n relations in the database". We recommend using [implicit](#implicit-many-to-many-relations) m-n-relations, where Prisma ORM automatically generates the relation table in the underlying database. [Explicit](#explicit-many-to-many-relations) m-n-relations should be used when you need to store additional data in the relations, such as the date the relation was created. ## MongoDB In MongoDB, m-n-relations are represented by: - relation fields on both sides, that each have a `@relation` attribute, with mandatory `fields` and `references` arguments - a scalar list of referenced IDs on each side, with a type that matches the ID field on the other side The following example demonstrates a m-n-relation between posts and categories: ```prisma model Post { id String @id @default(auto()) @map("_id") @db.ObjectId categoryIDs String[] @db.ObjectId categories Category[] @relation(fields: [categoryIDs], references: [id]) } model Category { id String @id @default(auto()) @map("_id") @db.ObjectId name String postIDs String[] @db.ObjectId posts Post[] @relation(fields: [postIDs], references: [id]) } ``` Prisma ORM validates m-n-relations in MongoDB with the following rules: - The fields on both sides of the relation must have a list type (in the example above, `categories` have a type of `Category[]` and `posts` have a type of `Post[]`) - The `@relation` attribute must define `fields` and `references` arguments on both sides - The `fields` argument must have only one scalar field defined, which must be of a list type - The `references` argument must have only one scalar field defined. This scalar field must exist on the referenced model and must be of the same type as the scalar field in the `fields` argument, but singular (no list) - The scalar field to which `references` points must have the `@id` attribute - No [referential actions](/orm/prisma-schema/data-model/relations/referential-actions) are allowed in `@relation` The implicit m-n-relations [used in relational databases](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations) are not supported on MongoDB. ### Querying MongoDB many-to-many relations This section demonstrates how to query m-n-relations in MongoDB, using the example schema above. The following query finds posts with specific matching category IDs: ```ts const newId1 = new ObjectId() const newId2 = new ObjectId() const posts = await prisma.post.findMany({ where: { categoryIDs: { hasSome: [newId1.toHexString(), newId2.toHexString()], }, }, }) ``` The following query finds posts where the category name contains the string `'Servers'`: ```ts const posts = await prisma.post.findMany({ where: { categories: { some: { name: { contains: 'Servers', }, }, }, }, }) ``` --- # Self-relations URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/self-relations A relation field can also reference its own model, in this case the relation is called a _self-relation_. Self-relations can be of any cardinality, 1-1, 1-n and m-n. Note that self-relations always require the `@relation` attribute. ## One-to-one self-relations The following example models a one-to-one self-relation: ```prisma model User { id Int @id @default(autoincrement()) name String? successorId Int? @unique successor User? @relation("BlogOwnerHistory", fields: [successorId], references: [id]) predecessor User? @relation("BlogOwnerHistory") } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId name String? successorId String? @unique @db.ObjectId successor User? @relation("BlogOwnerHistory", fields: [successorId], references: [id]) predecessor User? @relation("BlogOwnerHistory") } ``` This relation expresses the following: - "a user can have one or zero predecessors" (for example, Sarah is Mary's predecessor as blog owner) - "a user can have one or zero successors" (for example, Mary is Sarah's successor as blog owner) > **Note**: One-to-one self-relations cannot be made required on both sides. One or both sides must be optional, otherwise it becomes impossible to create the first `User` record. To create a one-to-one self-relation: - Both sides of the relation must define a `@relation` attribute that share the same name - in this case, **BlogOwnerHistory**. - One relation field must be a [fully annotated](/orm/prisma-schema/data-model/relations#relation-fields). In this example, the `successor` field defines both the `field` and `references` arguments. - One relation field must be backed by a foreign key. The `successor` field is backed by the `successorId` foreign key, which references a value in the `id` field. The `successorId` scalar relation field also requires a `@unique` attribute to guarantee a one-to-one relation. > **Note**: One-to-one self relations require two sides even if both sides are equal in the relationship. For example, to model a 'best friends' relation, you would need to create two relation fields: `bestfriend1` and a `bestfriend2`. Either side of the relation can be backed by a foreign key. In the previous example, repeated below, `successor` is backed by `successorId`: ```prisma highlight=4;normal model User { id Int @id @default(autoincrement()) name String? //highlight-next-line successorId Int? @unique successor User? @relation("BlogOwnerHistory", fields: [successorId], references: [id]) predecessor User? @relation("BlogOwnerHistory") } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId name String? //highlight-next-line successorId String? @unique @db.ObjectId successor User? @relation("BlogOwnerHistory", fields: [successorId], references: [id]) predecessor User? @relation("BlogOwnerHistory") } ``` Alternatively, you could rewrite this so that `predecessor` is backed by `predecessorId`: ```prisma model User { id Int @id @default(autoincrement()) name String? successor User? @relation("BlogOwnerHistory") //highlight-start predecessorId Int? @unique predecessor User? @relation("BlogOwnerHistory", fields: [predecessorId], references: [id]) //highlight-end } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId name String? successor User? @relation("BlogOwnerHistory") //highlight-start predecessorId String? @unique @db.ObjectId predecessor User? @relation("BlogOwnerHistory", fields: [predecessorId], references: [id]) //highlight-end } ``` No matter which side is backed by a foreign key, Prisma Client surfaces both the `predecessor` and `successor` fields: ```ts showLineNumbers const x = await prisma.user.create({ data: { name: "Bob McBob", //highlight-next-line successor: { connect: { id: 2, }, }, //highlight-next-line predecessor: { connect: { id: 4, }, }, }, }); ``` ### One-to-one self relations in the database ### Relational databases In **relational databases only**, a one-to-one self-relation is represented by the following SQL: ```sql CREATE TABLE "User" ( id SERIAL PRIMARY KEY, "name" TEXT, "successorId" INTEGER ); ALTER TABLE "User" ADD CONSTRAINT fk_successor_user FOREIGN KEY ("successorId") REFERENCES "User" (id); ALTER TABLE "User" ADD CONSTRAINT successor_unique UNIQUE ("successorId"); ``` ### MongoDB For MongoDB, Prisma ORM currently uses a [normalized data model design](https://www.mongodb.com/docs/manual/data-modeling/), which means that documents reference each other by ID in a similar way to relational databases. The following MongoDB documents represent a one-to-one self-relation between two users: ```json { "_id": { "$oid": "60d97df70080618f000e3ca9" }, "name": "Elsa the Elder" } ``` ```json { "_id": { "$oid": "60d97df70080618f000e3caa" }, "name": "Elsa", "successorId": { "$oid": "60d97df70080618f000e3ca9" } } ``` ## One-to-many self relations A one-to-many self-relation looks as follows: ```prisma model User { id Int @id @default(autoincrement()) name String? teacherId Int? teacher User? @relation("TeacherStudents", fields: [teacherId], references: [id]) students User[] @relation("TeacherStudents") } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId name String? teacherId String? @db.ObjectId teacher User? @relation("TeacherStudents", fields: [teacherId], references: [id]) students User[] @relation("TeacherStudents") } ``` This relation expresses the following: - "a user has zero or one _teachers_ " - "a user can have zero or more _students_" Note that you can also require each user to have a teacher by making the `teacher` field [required](/orm/prisma-schema/data-model/models#optional-and-mandatory-fields). ### One-to-many self-relations in the database ### Relational databases In relational databases, a one-to-many self-relation is represented by the following SQL: ```sql CREATE TABLE "User" ( id SERIAL PRIMARY KEY, "name" TEXT, "teacherId" INTEGER ); ALTER TABLE "User" ADD CONSTRAINT fk_teacherid_user FOREIGN KEY ("teacherId") REFERENCES "User" (id); ``` Notice the lack of `UNIQUE` constraint on `teacherId` - multiple students can have the same teacher. ### MongoDB For MongoDB, Prisma ORM currently uses a [normalized data model design](https://www.mongodb.com/docs/manual/data-modeling/), which means that documents reference each other by ID in a similar way to relational databases. The following MongoDB documents represent a one-to-many self-relation between three users - one teacher and two students with the same `teacherId`: ```json { "_id": { "$oid": "60d9b9e600fe3d470079d6f9" }, "name": "Ms. Roberts" } ``` ```json { "_id": { "$oid": "60d9b9e600fe3d470079d6fa" }, "name": "Student 8", "teacherId": { "$oid": "60d9b9e600fe3d470079d6f9" } } ``` ```json { "_id": { "$oid": "60d9b9e600fe3d470079d6fb" }, "name": "Student 9", "teacherId": { "$oid": "60d9b9e600fe3d470079d6f9" } } ``` ## Many-to-many self relations A many-to-many self-relation looks as follows: ```prisma model User { id Int @id @default(autoincrement()) name String? followedBy User[] @relation("UserFollows") following User[] @relation("UserFollows") } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId name String? followedBy User[] @relation("UserFollows", fields: [followedByIDs], references: [id]) followedByIDs String[] @db.ObjectId following User[] @relation("UserFollows", fields: [followingIDs], references: [id]) followingIDs String[] @db.ObjectId } ``` This relation expresses the following: - "a user can be followed by zero or more users" - "a user can follow zero or more users" Note that for relational databases, this many-to-many-relation is [implicit](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations). This means Prisma ORM maintains a [relation table](/orm/prisma-schema/data-model/relations/many-to-many-relations#relation-tables) for it in the underlying database. If you need the relation to hold other fields, you can create an [explicit](/orm/prisma-schema/data-model/relations/many-to-many-relations#explicit-many-to-many-relations) many-to-many self relation as well. The explicit version of the self relation shown previously is as follows: ```prisma model User { id Int @id @default(autoincrement()) name String? followedBy Follows[] @relation("followedBy") following Follows[] @relation("following") } model Follows { followedBy User @relation("followedBy", fields: [followedById], references: [id]) followedById Int following User @relation("following", fields: [followingId], references: [id]) followingId Int @@id([followingId, followedById]) } ``` ### Many-to-many self-relations in the database ### Relational databases In relational databases, a many-to-many self-relation (implicit) is represented by the following SQL: ```sql CREATE TABLE "User" ( id integer DEFAULT nextval('"User_id_seq"'::regclass) PRIMARY KEY, name text ); CREATE TABLE "_UserFollows" ( "A" integer NOT NULL REFERENCES "User"(id) ON DELETE CASCADE ON UPDATE CASCADE, "B" integer NOT NULL REFERENCES "User"(id) ON DELETE CASCADE ON UPDATE CASCADE ); ``` ### MongoDB For MongoDB, Prisma ORM currently uses a [normalized data model design](https://www.mongodb.com/docs/manual/data-modeling/), which means that documents reference each other by ID in a similar way to relational databases. The following MongoDB documents represent a many-to-many self-relation between five users - two users that follow `"Bob"`, and two users that follow him: ```json { "_id": { "$oid": "60d9866f00a3e930009a6cdd" }, "name": "Bob", "followedByIDs": [ { "$oid": "60d9866f00a3e930009a6cde" }, { "$oid": "60d9867000a3e930009a6cdf" } ], "followingIDs": [ { "$oid": "60d9867000a3e930009a6ce0" }, { "$oid": "60d9867000a3e930009a6ce1" } ] } ``` ```json { "_id": { "$oid": "60d9866f00a3e930009a6cde" }, "name": "Follower1", "followingIDs": [{ "$oid": "60d9866f00a3e930009a6cdd" }] } ``` ```json { "_id": { "$oid": "60d9867000a3e930009a6cdf" }, "name": "Follower2", "followingIDs": [{ "$oid": "60d9866f00a3e930009a6cdd" }] } ``` ```json { "_id": { "$oid": "60d9867000a3e930009a6ce0" }, "name": "CoolPerson1", "followedByIDs": [{ "$oid": "60d9866f00a3e930009a6cdd" }] } ``` ```json { "_id": { "$oid": "60d9867000a3e930009a6ce1" }, "name": "CoolPerson2", "followedByIDs": [{ "$oid": "60d9866f00a3e930009a6cdd" }] } ``` ## Defining multiple self-relations on the same model You can also define multiple self-relations on the same model at once. Taking all relations from the previous sections as example, you could define a `User` model as follows: ```prisma model User { id Int @id @default(autoincrement()) name String? teacherId Int? teacher User? @relation("TeacherStudents", fields: [teacherId], references: [id]) students User[] @relation("TeacherStudents") followedBy User[] @relation("UserFollows") following User[] @relation("UserFollows") } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId name String? teacherId String? @db.ObjectId teacher User? @relation("TeacherStudents", fields: [teacherId], references: [id]) students User[] @relation("TeacherStudents") followedBy User[] @relation("UserFollows", fields: [followedByIDs]) followedByIDs String[] @db.ObjectId following User[] @relation("UserFollows", fields: [followingIDs]) followingIDs String[] @db.ObjectId } ``` --- # Special rules for referential actions in SQL Server and MongoDB URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/referential-actions/special-rules-for-referential-actions Some databases have specific requirements that you should consider if you are using referential actions. - Microsoft SQL Server doesn't allow cascading referential actions on a foreign key, if the relation chain causes a cycle or multiple cascade paths. If the referential actions on the foreign key are set to something other than `NO ACTION` (or `NoAction` if Prisma ORM is managing referential integrity), the server will check for cycles or multiple cascade paths and return an error when executing the SQL. - With MongoDB, using referential actions in Prisma ORM requires that for any data model with self-referential relations or cycles between three models, you must set the referential action of `NoAction` to prevent the referential action emulations from looping infinitely. Be aware that by default, the `relationMode = "prisma"` mode is used for MongoDB, which means that Prisma ORM manages [referential integrity](/orm/prisma-schema/data-model/relations/relation-mode). Given the SQL: ```sql CREATE TABLE [dbo].[Employee] ( [id] INT NOT NULL IDENTITY(1,1), [managerId] INT, CONSTRAINT [PK__Employee__id] PRIMARY KEY ([id]) ); ALTER TABLE [dbo].[Employee] ADD CONSTRAINT [FK__Employee__managerId] FOREIGN KEY ([managerId]) REFERENCES [dbo].[Employee]([id]) ON DELETE CASCADE ON UPDATE CASCADE; ``` When the SQL is run, the database would throw the following error: ```terminal wrap Introducing FOREIGN KEY constraint 'FK__Employee__managerId' on table 'Employee' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. ``` In more complicated data models, finding the cascade paths can get complex. Therefore in Prisma ORM, the data model is validated _before_ generating any SQL to be run during any migrations, highlighting relations that are part of the paths. This makes it much easier to find and break these action chains. ## Self-relation (SQL Server and MongoDB) The following model describes a self-relation where an `Employee` can have a manager and managees, referencing entries of the same model. ```prisma model Employee { id Int @id @default(autoincrement()) manager Employee? @relation(name: "management", fields: [managerId], references: [id]) managees Employee[] @relation(name: "management") managerId Int? } ``` This will result in the following error: ```terminal wrap Error parsing attribute "@relation": A self-relation must have `onDelete` and `onUpdate` referential actions set to `NoAction` in one of the @relation attributes. (Implicit default `onDelete`: `SetNull`, and `onUpdate`: `Cascade`) ``` By not defining any actions, Prisma ORM will use the following default values depending if the underlying [scalar fields](/orm/prisma-schema/data-model/models#scalar-fields) are set to be optional or required. | Clause | All of the scalar fields are optional | At least one scalar field is required | | :--------- | :------------------------------------ | :------------------------------------ | | `onDelete` | `SetNull` | `NoAction` | | `onUpdate` | `Cascade` | `Cascade` | Since the default referential action for `onUpdate` in the above relation would be `Cascade` and for `onDelete` it would be `SetNull`, it creates a cycle and the solution is to explicitly set the `onUpdate` and `onDelete` values to `NoAction`. ```prisma highlight=3;delete|4;add model Employee { id Int @id @default(autoincrement()) //delete-next-line manager Employee @relation(name: "management", fields: [managerId], references: [id]) //add-next-line manager Employee @relation(name: "management", fields: [managerId], references: [id], onDelete: NoAction, onUpdate: NoAction) managees Employee[] @relation(name: "management") managerId Int } ``` ## Cyclic relation between three tables (SQL Server and MongoDB) The following models describe a cyclic relation between a `Chicken`, an `Egg` and a `Fox`, where each model references the other. ```prisma model Chicken { id Int @id @default(autoincrement()) egg Egg @relation(fields: [eggId], references: [id]) eggId Int predators Fox[] } model Egg { id Int @id @default(autoincrement()) predator Fox @relation(fields: [predatorId], references: [id]) predatorId Int parents Chicken[] } model Fox { id Int @id @default(autoincrement()) meal Chicken @relation(fields: [mealId], references: [id]) mealId Int foodStore Egg[] } ``` This will result in three validation errors in every relation field that is part of the cycle. The first one is in the relation `egg` in the `Chicken` model: ```terminal wrap Error parsing attribute "@relation": Reference causes a cycle. One of the @relation attributes in this cycle must have `onDelete` and `onUpdate` referential actions set to `NoAction`. Cycle path: Chicken.egg → Egg.predator → Fox.meal. (Implicit default `onUpdate`: `Cascade`) ``` The second one is in the relation `predator` in the `Egg` model: ```terminal wrap Error parsing attribute "@relation": Reference causes a cycle. One of the @relation attributes in this cycle must have `onDelete` and `onUpdate` referential actions set to `NoAction`. Cycle path: Egg.predator → Fox.meal → Chicken.egg. (Implicit default `onUpdate`: `Cascade`) ``` And the third one is in the relation `meal` in the `Fox` model: ```terminal wrap Error parsing attribute "@relation": Reference causes a cycle. One of the @relation attributes in this cycle must have `onDelete` and `onUpdate` referential actions set to `NoAction`. Cycle path: Fox.meal → Chicken.egg → Egg.predator. (Implicit default `onUpdate`: `Cascade`) ``` As the relation fields are required, the default referential action for `onDelete` is `NoAction` but for `onUpdate` it is `Cascade`, which causes a referential action cycle. The solution is to set the `onUpdate` value to `NoAction` in any one of the relations. ```prisma highlight=3;delete|4;add model Chicken { id Int @id @default(autoincrement()) //delete-next-line egg Egg @relation(fields: [eggId], references: [id]) //add-next-line egg Egg @relation(fields: [eggId], references: [id], onUpdate: NoAction) eggId Int predators Fox[] } ``` or ```prisma highlight=3;delete|4;add model Egg { id Int @id @default(autoincrement()) //delete-next-line predator Fox @relation(fields: [predatorId], references: [id]) //add-next-line predator Fox @relation(fields: [predatorId], references: [id], onUpdate: NoAction) predatorId Int parents Chicken[] } ``` or ```prisma highlight=3;delete|4;add model Fox { id Int @id @default(autoincrement()) //delete-next-line meal Chicken @relation(fields: [mealId], references: [id]) //add-next-line meal Chicken @relation(fields: [mealId], references: [id], onUpdate: NoAction) mealId Int foodStore Egg[] } ``` ## Multiple cascade paths between two models (SQL Server only) The data model describes two different paths between same models, with both relations triggering cascading referential actions. ```prisma model User { id Int @id @default(autoincrement()) comments Comment[] posts Post[] } model Post { id Int @id @default(autoincrement()) authorId Int author User @relation(fields: [authorId], references: [id]) comments Comment[] } model Comment { id Int @id @default(autoincrement()) writtenById Int postId Int writtenBy User @relation(fields: [writtenById], references: [id]) post Post @relation(fields: [postId], references: [id]) } ``` The problem in this data model is how there are two paths from `Comment` to the `User`, and how the default `onUpdate` action in both relations is `Cascade`. This leads into two validation errors: The first one is in the relation `writtenBy`: ```terminal wrap Error parsing attribute "@relation": When any of the records in model `User` is updated or deleted, the referential actions on the relations cascade to model `Comment` through multiple paths. Please break one of these paths by setting the `onUpdate` and `onDelete` to `NoAction`. (Implicit default `onUpdate`: `Cascade`) ``` The second one is in the relation `post`: ```terminal wrap Error parsing attribute "@relation": When any of the records in model `User` is updated or deleted, the referential actions on the relations cascade to model `Comment` through multiple paths. Please break one of these paths by setting the `onUpdate` and `onDelete` to `NoAction`. (Implicit default `onUpdate`: `Cascade`) ``` The error means that by updating a primary key in a record in the `User` model, the update will cascade once between the `Comment` and `User` through the `writtenBy` relation, and again through the `Post` model from the `post` relation due to `Post` being related with the `Comment` model. The fix is to set the `onUpdate` referential action to `NoAction` in the `writtenBy` or `post` relation fields, or from the `Post` model by changing the actions in the `author` relation: ```prisma highlight=5;delete|6;add model Comment { id Int @id @default(autoincrement()) writtenById Int postId Int //delete-next-line writtenBy User @relation(fields: [writtenById], references: [id]) //add-next-line writtenBy User @relation(fields: [writtenById], references: [id], onUpdate: NoAction) post Post @relation(fields: [postId], references: [id]) } ``` or ```prisma highlight=6;delete|7;add model Comment { id Int @id @default(autoincrement()) writtenById Int postId Int writtenBy User @relation(fields: [writtenById], references: [id]) //delete-next-line post Post @relation(fields: [postId], references: [id]) //add-next-line post Post @relation(fields: [postId], references: [id], onUpdate: NoAction) } ``` or ```prisma highlight=4;delete|5;add model Post { id Int @id @default(autoincrement()) authorId Int //delete-next-line author User @relation(fields: [authorId], references: [id]) //add-next-line author User @relation(fields: [authorId], references: [id], onUpdate: NoAction) comments Comment[] } ``` --- # Referential actions URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/referential-actions/index 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](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature) `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. ```prisma file=schema.prisma highlight=4;normal showLineNumbers 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](#referential-action-defaults). If you upgrade from a version earlier than 2.26.0: It is extremely important that you check the [upgrade paths for referential actions](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/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](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/referential-actions#prisma-orm-2x-default-referential-actions) - `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`](/orm/prisma-client/queries/crud#update) or [`delete`](/orm/prisma-client/queries/crud#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](/orm/prisma-schema/data-model/relations#relation-fields), **which do not exist on the database**, and [scalar fields](/orm/prisma-schema/data-model/models#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`](/orm/reference/prisma-schema-reference#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](#referential-action-defaults). 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: ```prisma file=schema.prisma highlight=10,16-17;normal showLineNumbers 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 in `TagOnPosts`, using the `Cascade` referential action - If you delete a `User`, the author is removed from all posts by setting the field value to `Null`, because of the `SetNull` referential action. To allow this, `User` and `userId` must be optional fields in `Post`. Prisma ORM supports the following referential actions: - [`Cascade`](#cascade) - [`Restrict`](#restrict) - [`NoAction`](#noaction) - [`SetNull`](#setnull) - [`SetDefault`](#setdefault) ### 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: ```prisma highlight=4;normal model Post { id Int @id @default(autoincrement()) title String //highlight-next-line 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](/orm/prisma-schema/data-model/relations/many-to-many-relations#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](/orm/prisma-schema/data-model/relations/troubleshooting-relations#how-to-use-a-relation-table-with-a-many-to-many-relationship). - 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](https://github.com/prisma/prisma/issues/7909) 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](#mysqlmariadb). - ⌘ See [special cases for PostgreSQL](#postgresql). - ‡ See [special cases for SQL Server](#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 for `NoAction`. You can define tables using the `SET 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`](#restrict) is not available for SQL Server databases, but you can use [`NoAction`](#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 ```prisma file=schema.prisma highlight=4;add showLineNumbers model Post { id Int @id @default(autoincrement()) title String //add-next-line 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 ```prisma file=schema.prisma highlight=4;add showLineNumbers model Post { id Int @id @default(autoincrement()) title String //add-next-line 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](/orm/overview/databases/sql-server) and triggers a schema validation error. Instead, you can use [`NoAction`](#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](https://www.postgresql.org/docs/current/ddl-constraints.html#DDL-CONSTRAINTS-FK) for more information. - **MySQL**: `NoAction` behaves exactly the same as `Restrict`. See [the MySQL docs](https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html#foreign-key-referential-actions) for more information. - **SQLite**: When a related primary key is modified or deleted, no action is taken. See [the SQLite docs](https://www.sqlite.org/foreignkeys.html#fk_actions) for more information. - **SQL Server**: When a referenced record is deleted or modified, an error is raised. See [the SQL Server docs](https://learn.microsoft.com/en-us/sql/relational-databases/tables/graph-edge-constraints?view=sql-server-ver15#on-delete-referential-actions-on-edge-constraints) 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](/orm/prisma-schema/data-model/relations/relation-mode#emulate-relations-in-prisma-orm-with-the-prisma-relation-mode) 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. #### Example usage ```prisma file=schema.prisma highlight=4;add showLineNumbers model Post { id Int @id @default(autoincrement()) title String //add-next-line author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction) authorId Int } model User { id Int @id @default(autoincrement()) posts Post[] } ``` ##### Result of using `NoAction` `User`'s with posts **cannot** be deleted. The `User`'s `id` **cannot** be changed. ### `SetNull` - `onDelete: SetNull` The scalar field of the referencing object will be set to `NULL`. - `onUpdate: SetNull` When updating the identifier of a referenced object, the scalar fields of the referencing objects will be set to `NULL`. `SetNull` will only work on optional relations. On required relations, a runtime error will be thrown since the scalar fields cannot be null. ```prisma file=schema.prisma highlight=4;add showLineNumbers model Post { id Int @id @default(autoincrement()) title String //add-next-line author User? @relation(fields: [authorId], references: [id], onDelete: SetNull, onUpdate: SetNull) authorId Int? } model User { id Int @id @default(autoincrement()) posts Post[] } ``` ##### Result of using `SetNull` When deleting a `User`, the `authorId` will be set to `NULL` for all its authored posts. When changing a `User`'s `id`, the `authorId` will be set to `NULL` for all its authored posts. ### `SetDefault` - `onDelete: SetDefault` The scalar field of the referencing object will be set to the fields default value. - `onUpdate: SetDefault` The scalar field of the referencing object will be set to the fields default value. These require setting a default for the relation scalar field with [`@default`](/orm/reference/prisma-schema-reference#default). If no defaults are provided for any of the scalar fields, a runtime error will be thrown. ```prisma file=schema.prisma highlight=4,5;add showLineNumbers model Post { id Int @id @default(autoincrement()) title String //add-start authorUsername String? @default("anonymous") author User? @relation(fields: [authorUsername], references: [username], onDelete: SetDefault, onUpdate: SetDefault) //add-end } model User { username String @id posts Post[] } ``` ##### Result of using `SetDefault` When deleting a `User`, its existing posts' `authorUsername` field values will be set to 'anonymous'. When the `username` of a `User` changes, its existing posts' `authorUsername` field values will be set to 'anonymous'. ### Database-specific requirements MongoDB and SQL Server have specific requirements for referential actions if you have [self-relations](/orm/prisma-schema/data-model/relations/referential-actions/special-rules-for-referential-actions#self-relation-sql-server-and-mongodb) or [cyclic relations](/orm/prisma-schema/data-model/relations/referential-actions/special-rules-for-referential-actions#cyclic-relation-between-three-tables-sql-server-and-mongodb) in your data model. SQL Server also has specific requirements if you have relations with [multiple cascade paths](/orm/prisma-schema/data-model/relations/referential-actions/special-rules-for-referential-actions#multiple-cascade-paths-between-two-models-sql-server-only). ## Upgrade paths from versions 2.25.0 and earlier There are a couple of paths you can take when upgrading which will give different results depending on the desired outcome. If you currently use the migration workflow, you can run an introspection to check how the defaults are reflected in your schema. You can then manually update your database if you need to. You can also decide to skip checking the defaults and run a migration to update your database with the [new default values](#referential-action-defaults). The following assumes you have upgraded to 2.26.0 or newer and enabled the preview feature flag, or upgraded to 3.0.0 or newer: ### Using Introspection If you [Introspect](/orm/prisma-schema/introspection) your database, the referential actions configured at the database level will be reflected in your Prisma Schema. If you have been using Prisma Migrate or `prisma db push` to manage the database schema, these are likely to be the [default values](#referential-action-defaults) from 2.25.0 and earlier. When you run an Introspection, Prisma ORM compares all the foreign keys in the database with the schema, if the SQL statements `ON DELETE` and `ON UPDATE` do **not** match the default values, they will be explicitly set in the schema file. After introspecting, you can review the non-default clauses in your schema. The most important clause to review is `onDelete`, which defaults to `Cascade` in 2.25.0 and earlier. If you are using either the [`delete()`](/orm/prisma-client/queries/crud#delete-a-single-record) or [`deleteMany()`](/orm/prisma-client/queries/crud#delete-all-records) methods, **[cascading deletes](#how-to-use-cascading-deletes) will now be performed** as the `referentialActions` preview feature **removed the safety net in Prisma Client that previously prevented cascading deletes at runtime**. Be sure to check your code and make any adjustments accordingly. Make sure you are happy with every case of `onDelete: Cascade` in your schema. If not, either: - Modify your Prisma schema and `db push` or `dev migrate` to change the database _or_ - Manually update the underlying database if you use an introspection-only workflow The following example would result in a cascading delete, if the `User` is deleted then all of their `Post`'s will be deleted too. #### A blog schema example ```prisma showLineNumbers model Post { id Int @id @default(autoincrement()) title String //add-next-line author User @relation(fields: [authorId], references: [id], onDelete: Cascade) authorId Int } model User { id Int @id @default(autoincrement()) posts Post[] } ``` ### Using Migration When running a [Migration](/orm/prisma-migrate) (or the [`prisma db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) command) the [new defaults](#referential-action-defaults) will be applied to your database. Unlike when you run an Introspect for the first time, the new referential actions clause and property, will **not** automatically be added to your prisma schema by the Prisma VSCode extension. You will have to manually add them if you wish to use anything other than the new defaults. Explicitly defining referential actions in your Prisma schema is optional. If you do not explicitly define a referential action for a relation, Prisma ORM uses the [new defaults](#referential-action-defaults). Note that referential actions can be added on a case by case basis. This means that you can add them to one single relation and leave the rest set to the defaults by not manually specifying anything. ### Checking for errors **Before** upgrading to 2.26.0 and enabling the referential actions **preview feature**, Prisma ORM prevented the deletion of records while using `delete()` or `deleteMany()` to preserve referential integrity. A custom runtime error would be thrown by Prisma Client with the error code `P2014`. **After** upgrading and enabling the referential actions **preview feature**, Prisma ORM no longer performs runtime checks. You can instead specify a custom referential action to preserve the referential integrity between relations. When you use [`NoAction`](#noaction) or [`Restrict`](#restrict) to prevent the deletion of records, the error messages will be different post 2.26.0 compared to pre 2.26.0. This is because they are now triggered by the database and **not** Prisma Client. The new error code that can be expected is `P2003`. To make sure you catch these new errors you can adjust your code accordingly. #### Example of catching errors The following example uses the below blog schema with a one-to-many relationship between `Post` and `User` and sets a [`Restrict`](#restrict) referential actions on the `author` field. This means that if a user has a post, that user (and their posts) **cannot** be deleted. ```prisma file=schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) title String author User @relation(fields: [authorId], references: [id], onDelete: Restrict) authorId String } model User { id Int @id @default(autoincrement()) posts Post[] } ``` Prior to upgrading and enabling the referential actions **preview feature**, the error code you would receive when trying to delete a user which has posts would be `P2014` and it's message: > "The change you are trying to make would violate the required relation '\{relation_name}' between the \{model_a_name\} and \{model_b_name\} models." ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { try { await prisma.user.delete({ where: { id: 'some-long-id', }, }) } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { if (error.code === 'P2014') { console.log(error.message) } } } } main() ``` To make sure you are checking for the correct errors in your code, modify your check to look for `P2003`, which will deliver the message: > "Foreign key constraint failed on the field: \{field_name\}" ```ts highlight=14;delete|15;add import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { try { await prisma.user.delete({ where: { id: 'some-long-id' } }) } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { //delete-next-line if (error.code === 'P2014') { //add-next-line if (error.code === 'P2003') { console.log(error.message) } } } } main() ``` --- # Relation mode URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/relation-mode In Prisma schema, relations between records are defined with the [`@relation`](/orm/reference/prisma-schema-reference#relation) attribute. For example, in the following schema there is a one-to-many relation between the `User` and `Post` models: ```prisma file=schema.prisma highlight=4,5,10;normal showLineNumbers model Post { id Int @id @default(autoincrement()) title String //highlight-start author User @relation(fields: [authorId], references: [id], onDelete: Cascade, onUpdate: Cascade) authorId Int //highlight-end } model User { id Int @id @default(autoincrement()) //highlight-next-line posts Post[] } ``` Prisma ORM has two _relation modes_, `foreignKeys` and `prisma`, that specify how relations between records are enforced. If you use Prisma ORM with a relational database, then by default Prisma ORM uses the [`foreignKeys` relation mode](#handle-relations-in-your-relational-database-with-the-foreignkeys-relation-mode), which enforces relations between records at the database level with foreign keys. A foreign key is a column or group of columns in one table that take values based on the primary key in another table. Foreign keys allow you to: - set constraints that prevent you from making changes that break references - set [referential actions](/orm/prisma-schema/data-model/relations/referential-actions) that define how changes to records are handled Together these constraints and referential actions guarantee the _referential integrity_ of the data. For the example schema above, Prisma Migrate will generate the following SQL by default if you use the PostgreSQL connector: ```sql highlight=19-22;normal -- CreateTable CREATE TABLE "Post" ( "id" SERIAL NOT NULL, "title" TEXT NOT NULL, "authorId" INTEGER NOT NULL, CONSTRAINT "Post_pkey" PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "User" ( "id" SERIAL NOT NULL, CONSTRAINT "User_pkey" PRIMARY KEY ("id") ); -- AddForeignKey //highlight-start ALTER TABLE "Post" ADD CONSTRAINT "Post_authorId_fkey" FOREIGN KEY ("authorId") REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; //highlight-end ``` In this case, the foreign key constraint on the `authorId` column of the `Post` table references the `id` column of the `User` table, and guarantees that a post must have an author that exists. If you update or delete a user then the `ON DELETE` and `ON UPDATE` referential actions specify the `CASCADE` option, which will also delete or update all posts belonging to the user. Some databases, such as MongoDB or [PlanetScale](/orm/overview/databases/planetscale#differences-to-consider), do not support foreign keys. Additionally, in some cases developers may prefer not to use foreign keys in their relational database that usually does support foreign keys. For these situations, Prisma ORM offers [the `prisma` relation mode](#emulate-relations-in-prisma-orm-with-the-prisma-relation-mode), which emulates some properties of relations in relational databases. When you use Prisma Client with the `prisma` relation mode enabled, the behavior of queries is identical or similar, but referential actions and some constraints are handled by the Prisma engine rather than in the database. There are performance implications to emulation of referential integrity and referential actions in Prisma Client. In cases where the underlying database supports foreign keys, it is usually the preferred choice. ## How to set the relation mode in your Prisma schema To set the relation mode, add the `relationMode` field in the `datasource` block: ```prisma file=schema.prisma highlight=4,9;add showLineNumbers datasource db { provider = "mysql" url = env("DATABASE_URL") //add-next-line relationMode = "prisma" } ``` The ability to set the relation mode was introduced as part of the `referentialIntegrity` preview feature in Prisma ORM version 3.1.1, and is generally available in Prisma ORM versions 4.8.0 and later.

The `relationMode` field was renamed in Prisma ORM version 4.5.0, and was previously named `referentialIntegrity`.
For relational databases, the available options are: - `foreignKeys`: this handles relations in the database with foreign keys. This is the default option for all relational database connectors and is active if no `relationMode` is explicitly set in the `datasource` block. - `prisma`: this emulates relations in Prisma Client. You should also [enable this option](/orm/overview/databases/planetscale#option-1-emulate-relations-in-prisma-client) when you use the MySQL connector with a PlanetScale database and don't have native foreign key constraints enabled in your PlanetScale database settings. For MongoDB, the only available option is the `prisma` relation mode. This mode is also active if no `relationMode` is explicitly set in the `datasource` block. If you switch between relation modes, Prisma ORM will add or remove foreign keys to your database next time you apply changes to your schema with Prisma Migrate or `db push`. See [Switch between relation modes](#switch-between-relation-modes) for more information. ## Handle relations in your relational database with the `foreignKeys` relation mode The `foreignKeys` relation mode handles relations in your relational database with foreign keys. This is the default option when you use a relational database connector (PostgreSQL, MySQL, SQLite, SQL Server, CockroachDB). The `foreignKeys` relation mode is not available when you use the MongoDB connector. Some relational databases, [such as PlanetScale](/orm/overview/databases/planetscale#option-1-emulate-relations-in-prisma-client), also forbid the use of foreign keys. In these cases, you should instead [emulate relations in Prisma ORM with the `prisma` relation mode](#emulate-relations-in-prisma-orm-with-the-prisma-relation-mode). ### Referential integrity The `foreignKeys` relation mode maintains referential integrity at the database level with foreign key constraints and referential actions. #### Foreign key constraints When you _create_ or _update_ a record with a relation to another record, the related record needs to exist. Foreign key constraints enforce this behavior in the database. If the record does not exist, the database will return an error message. #### Referential actions When you _update_ or _delete_ a record with a relation to another record, referential actions are triggered in the database. To maintain referential integrity in related records, referential actions prevent changes that would break referential integrity, cascade changes through to related records, or set the value of fields that reference the updated or deleted records to a `null` or default value. For more information, see the [referential actions](/orm/prisma-schema/data-model/relations/referential-actions) page. ### Introspection When you introspect a relational database with the `db pull` command with the `foreignKeys` relation mode enabled, a `@relation` attribute will be added to your Prisma schema for relations where foreign keys exist. ### Prisma Migrate and `db push` When you apply changes to your Prisma schema with Prisma Migrate or `db push` with the `foreignKeys` relation mode enabled, foreign keys will be created in your database for all `@relation` attributes in your schema. ## Emulate relations in Prisma ORM with the `prisma` relation mode The `prisma` relation mode emulates some foreign key constraints and referential actions for each Prisma Client query to maintain referential integrity, using some additional database queries and logic. The `prisma` relation mode is the default option for the MongoDB connector. It should also be set if you use a relational database that does not support foreign keys. For example, [if you use PlanetScale](/orm/overview/databases/planetscale#option-1-emulate-relations-in-prisma-client) without foreign key constraints, you should use the `prisma` relation mode. There are performance implications to emulation of referential integrity in Prisma Client, because it uses additional database queries to maintain referential integrity. In cases where the underlying database can handle referential integrity with foreign keys, it is usually the preferred choice. Emulation of relations is only available for Prisma Client queries and does not apply to raw queries. ### Which foreign key constraints are emulated? When you _update_ a record, Prisma ORM will emulate foreign key constraints. This means that when you update a record with a relation to another record, the related record needs to exist. If the record does not exist, Prisma Client will return an error message. However, when you _create_ a record, Prisma ORM does not emulate any foreign key constraints. You will be able to create invalid data. ### Which referential actions are emulated? When you _update_ or _delete_ a record with related records, Prisma ORM will emulate referential actions. The following table shows which emulated referential actions are available for each database connector: | Database | Cascade | Restrict | NoAction | SetNull | SetDefault | | :---------- | :------ | :------- | :------- | :------ | :--------- | | PostgreSQL | **✔️** | **✔️** | **❌**‡ | **✔️** | **❌**† | | MySQL | **✔️** | **✔️** | **✔️** | **✔️** | **❌**† | | SQLite | **✔️** | **✔️** | **❌**‡ | **✔️** | **❌**† | | SQL Server | **✔️** | **✔️** | **✔️** | **✔️** | **❌**† | | CockroachDB | **✔️** | **✔️** | **✔️** | **✔️** | **❌**† | | MongoDB | **✔️** | **✔️** | **✔️** | **✔️** | **❌**† | - † The `SetDefault` referential action is not supported in the `prisma` relation mode. - ‡ The `NoAction` referential action is not supported in the `prisma` relation mode for PostgreSQL and SQLite. Instead, use the `Restrict` action. ### Error messages Error messages returned by emulated constraints and referential actions in the `prisma` relation mode are generated by Prisma Client and differ slightly from the error messages in the `foreignKeys` relation mode: ```jsx Example: // foreignKeys: ... Foreign key constraint failed on the field: `ProfileOneToOne_userId_fkey (index)` // prisma: ... The change you are trying to make would violate the required relation 'ProfileOneToOneToUserOneToOne' between the `ProfileOneToOne` and `UserOneToOne` models. ``` ### Introspection When you introspect a database with the `db pull` command with the `prisma` relation mode enabled, relations will not be automatically added to your schema. You will instead need to add any relations manually with the `@relation` attribute. This only needs to be done once – next time you introspect your database, Prisma ORM will keep your added `@relation` attributes. ### Prisma Migrate and `db push` When you apply changes to your Prisma schema with Prisma Migrate or `db push` with the `prisma` relation mode enabled, Prisma ORM will not use foreign keys in your database. ### Indexes In relational databases that use foreign key constraints, the database usually also implicitly creates an index for the foreign key columns. For example, [MySQL will create an index on all foreign key columns](https://dev.mysql.com/doc/refman/8.0/en/constraint-foreign-key.html#:~:text=MySQL%20requires%20that%20foreign%20key%20columns%20be%20indexed%3B%20if%20you%20create%20a%20table%20with%20a%20foreign%20key%20constraint%20but%20no%20index%20on%20a%20given%20column%2C%20an%20index%20is%20created.). This is to allow foreign key checks to run fast and not require a table scan. The `prisma` relation mode does not use foreign keys, so no indexes are created when you use Prisma Migrate or `db push` to apply changes to your database. You instead need to manually add an index on your relation scalar fields with the [`@@index`](/orm/reference/prisma-schema-reference#index) attribute (or the [`@unique`](/orm/reference/prisma-schema-reference#unique), [`@@unique`](/orm/reference/prisma-schema-reference#unique-1) or [`@@id`](/orm/reference/prisma-schema-reference#id-1) attributes, if applicable). #### Index validation If you do not add the index manually, queries might require full table scans. This can be slow, and also expensive on database providers that bill per accessed row. To help avoid this, Prisma ORM warns you when your schema contains fields that are used in a `@relation` that does not have an index defined. For example, take the following schema with a relation between the `User` and `Post` models: ```prisma file=schema.prisma showLineNumbers datasource db { provider = "mysql" url = env("DATABASE_URL") relationMode = "prisma" } model User { id Int @id posts Post[] } model Post { id Int @id userId Int user User @relation(fields: [userId], references: [id]) } ``` Prisma ORM displays the following warning when you run `prisma format` or `prisma validate`: ```terminal wrap With `relationMode = "prisma"`, no foreign keys are used, so relation fields will not benefit from the index usually created by the relational database under the hood. This can lead to poor performance when querying these fields. We recommend adding an index manually. ``` To fix this, add an index to your `Post` model: ```prisma file=schema.prisma highlight=6;add showLineNumbers model Post { id Int @id userId Int user User @relation(fields: [userId], references: [id]) //add-next-line @@index([userId]) } ``` If you use the [Prisma VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) (or our [language server in another editor](/orm/more/development-environment/editor-setup)), the warning is augmented with a Quick Fix that adds the required index for you: ![The Quick Fix pop-up for adding an index on a relation scalar field in VS Code](./quick-fix-index.png) ## Switch between relation modes It is only possible to switch between relation modes when you use a relational database connector (PostgreSQL, MySQL, SQLite, SQL Server, CockroachDB). ### Switch from `foreignKeys` to `prisma` The default relation mode if you use a relational database and do not include the `relationMode` field in your `datasource` block is `foreignKeys`. To switch to the `prisma` relation mode, add the `relationMode` field with a value of `prisma`, or update the `relationMode` field value to `prisma` if it already exists. When you switch the relation mode from `foreignKeys` to `prisma`, after you first apply changes to your schema with Prisma Migrate or `db push` Prisma ORM will remove all previously created foreign keys in the next migration. If you keep the same database, you can then continue to work as normal. If you switch to a database that does not support foreign keys at all, your existing migration history contains SQL DDL that creates foreign keys, which might trigger errors if you ever have to rerun these migrations. In this case, we recommend that you delete the `migrations` directory. (If you use PlanetScale, which does not support foreign keys, we generally recommend that you [use `db push` rather than Prisma Migrate](/orm/overview/databases/planetscale#differences-to-consider).) ### Switch from `prisma` to `foreignKeys` To switch from the `prisma` relation mode to the `foreignKeys` relation mode, update the `relationMode` field value from `prisma` to `foreignKeys`. To do this, the database must support foreign keys. When you apply changes to your schema with Prisma Migrate or `db push` for the first time after you switch relation modes, Prisma ORM will create foreign keys for all relations in the next migration. --- # Troubleshooting relations URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/troubleshooting-relations Modelling your schema can sometimes offer up some unexpected results. This section aims to cover the most prominent of those. ## Implicit many-to-many self-relations return incorrect data if order of relation fields change ### Problem In the following implicit many-to-many self-relation, the lexicographic order of relation fields in `a_eats` (1) and `b_eatenBy` (2): ```prisma highlight=4,5;normal model Animal { id Int @id @default(autoincrement()) name String //highlight-start a_eats Animal[] @relation(name: "FoodChain") b_eatenBy Animal[] @relation(name: "FoodChain") //highlight-end } ``` The resulting relation table in SQL looks as follows, where `A` represents prey (`a_eats`) and `B` represents predators (`b_eatenBy`): | A | B | | :----------- | :--------- | | 8 (Plankton) | 7 (Salmon) | | 7 (Salmon) | 9 (Bear) | The following query returns a salmon's prey and predators: ```ts const getAnimals = await prisma.animal.findMany({ where: { name: 'Salmon', }, include: { b_eats: true, a_eatenBy: true, }, }) ``` ```js no-copy { "id": 7, "name": "Salmon", "b_eats": [ { "id": 8, "name": "Plankton" } ], "a_eatenBy": [ { "id": 9, "name": "Bear" } ] } ``` Now change the order of the relation fields: ```prisma highlight=4,5;normal model Animal { id Int @id @default(autoincrement()) name String //highlight-start b_eats Animal[] @relation(name: "FoodChain") a_eatenBy Animal[] @relation(name: "FoodChain") //highlight-end } ``` Migrate your changes and re-generate Prisma Client. When you run the same query with the updated field names, Prisma Client returns incorrect data (salmon now eats bears and gets eaten by plankton): ```ts const getAnimals = await prisma.animal.findMany({ where: { name: 'Salmon', }, include: { b_eats: true, a_eatenBy: true, }, }) ``` ```js no-copy { "id": 1, "name": "Salmon", "b_eats": [ { "id": 3, "name": "Bear" } ], "a_eatenBy": [ { "id": 2, "name": "Plankton" } ] } ``` Although the lexicographic order of the relation fields in the Prisma schema changed, columns `A` and `B` in the database **did not change** (they were not renamed and data was not moved). Therefore, `A` now represents predators (`a_eatenBy`) and `B` represents prey (`b_eats`): | A | B | | :----------- | :--------- | | 8 (Plankton) | 7 (Salmon) | | 7 (Salmon) | 9 (Bear) | ### Solution If you rename relation fields in an implicit many-to-many self-relations, make sure that you maintain the alphabetic order of the fields - for example, by prefixing with `a_` and `b_`. ## How to use a relation table with a many-to-many relationship There are a couple of ways to define an m-n relationship, implicitly or explicitly. Implicitly means letting Prisma ORM handle the relation table (JOIN table) under the hood, all you have to do is define an array/list for the non scalar types on each model, see [implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations). Where you might run into trouble is when creating an [explicit m-n relationship](/orm/prisma-schema/data-model/relations/many-to-many-relations#explicit-many-to-many-relations), that is, to create and handle the relation table yourself. **It can be overlooked that Prisma ORM requires both sides of the relation to be present**. Take the following example, here a relation table is created to act as the JOIN between the `Post` and `Category` tables. This will not work however as the relation table (`PostCategories`) must form a 1-to-many relationship with the other two models respectively. The back relation fields are missing from the `Post` to `PostCategories` and `Category` to `PostCategories` models. ```prisma // This example schema shows how NOT to define an explicit m-n relation model Post { id Int @id @default(autoincrement()) title String categories Category[] // This should refer to PostCategories } model PostCategories { post Post @relation(fields: [postId], references: [id]) postId Int category Category @relation(fields: [categoryId], references: [id]) categoryId Int @@id([postId, categoryId]) } model Category { id Int @id @default(autoincrement()) name String posts Post[] // This should refer to PostCategories } ``` To fix this the `Post` model needs to have a many relation field defined with the relation table `PostCategories`. The same applies to the `Category` model. This is because the relation model forms a 1-to-many relationship with the other two models its joining. ```prisma highlight=5,21;add|4,20;delete model Post { id Int @id @default(autoincrement()) title String //delete-next-line categories Category[] //add-next-line postCategories PostCategories[] } model PostCategories { post Post @relation(fields: [postId], references: [id]) postId Int category Category @relation(fields: [categoryId], references: [id]) categoryId Int @@id([postId, categoryId]) } model Category { id Int @id @default(autoincrement()) name String //delete-next-line posts Post[] //add-next-line postCategories PostCategories[] } ``` ## Using the `@relation` attribute with a many-to-many relationship It might seem logical to add a `@relation("Post")` annotation to a relation field on your model when composing an implicit many-to-many relationship. ```prisma model Post { id Int @id @default(autoincrement()) title String categories Category[] @relation("Category") Category Category? @relation("Post", fields: [categoryId], references: [id]) categoryId Int? } model Category { id Int @id @default(autoincrement()) name String posts Post[] @relation("Post") Post Post? @relation("Category", fields: [postId], references: [id]) postId Int? } ``` This however tells Prisma ORM to expect **two** separate one-to-many relationships. See [disambiguating relations](/orm/prisma-schema/data-model/relations#disambiguating-relations) for more information on using the `@relation` attribute. The following example is the correct way to define an implicit many-to-many relationship. ```prisma highlight=4,11;delete|5,12;add model Post { id Int @id @default(autoincrement()) title String //delete-next-line categories Category[] @relation("Category") //add-next-line categories Category[] } model Category { id Int @id @default(autoincrement()) name String //delete-next-line posts Post[] @relation("Post") //add-next-line posts Post[] } ``` The `@relation` annotation can also be used to [name the underlying relation table](/orm/prisma-schema/data-model/relations/many-to-many-relations#configuring-the-name-of-the-relation-table-in-implicit-many-to-many-relations) created on a implicit many-to-many relationship. ```prisma model Post { id Int @id @default(autoincrement()) title String categories Category[] @relation("CategoryPostRelation") } model Category { id Int @id @default(autoincrement()) name String posts Post[] @relation("CategoryPostRelation") } ``` ## Using m-n relations in databases with enforced primary keys ### Problem Some cloud providers enforce the existence of primary keys in all tables. However, any relation tables (JOIN tables) created by Prisma ORM (expressed via `@relation`) for many-to-many relations using implicit syntax do not have primary keys. ### Solution You need to use [explicit relation syntax](/orm/prisma-schema/data-model/relations/many-to-many-relations#explicit-many-to-many-relations), manually create the join model, and verify that this join model has a primary key. --- # Relations URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/relations/index A relation is a _connection_ between two models in the Prisma schema. For example, there is a one-to-many relation between `User` and `Post` because one user can have many blog posts. The following Prisma schema defines a one-to-many relation between the `User` and `Post` models. The fields involved in defining the relation are highlighted: ```prisma highlight=3,8,9;normal model User { id Int @id @default(autoincrement()) //highlight-next-line posts Post[] } model Post { id Int @id @default(autoincrement()) //highlight-start author User @relation(fields: [authorId], references: [id]) authorId Int // relation scalar field (used in the `@relation` attribute above) //highlight-end title String } ``` ```prisma highlight=3,8,9;normal model User { id String @id @default(auto()) @map("_id") @db.ObjectId //highlight-next-line posts Post[] } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId //highlight-start author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId // relation scalar field (used in the `@relation` attribute above) //highlight-end title String } ``` At a Prisma ORM level, the `User` / `Post` relation is made up of: - Two [relation fields](#relation-fields): `author` and `posts`. Relation fields define connections between models at the Prisma ORM level and **do not exist in the database**. These fields are used to generate Prisma Client. - The scalar `authorId` field, which is referenced by the `@relation` attribute. This field **does exist in the database** - it is the foreign key that connects `Post` and `User`. At a Prisma ORM level, a connection between two models is **always** represented by a [relation field](#relation-fields) on **each side** of the relation.
## Relations in the database ### Relational databases The following entity relationship diagram defines the same one-to-many relation between the `User` and `Post` tables in a **relational database**: ![A one-to-many relationship between a user and posts table.](./one-to-many.png) In SQL, you use a _foreign key_ to create a relation between two tables. Foreign keys are stored on **one side** of the relation. Our example is made up of: - A foreign key column in the `Post` table named `authorId`. - A primary key column in the `User` table named `id`. The `authorId` column in the `Post` table references the `id` column in the `User` table. In the Prisma schema, the foreign key / primary key relationship is represented by the `@relation` attribute on the `author` field: ```prisma author User @relation(fields: [authorId], references: [id]) ``` > **Note**: Relations in the Prisma schema represent relationships that exist between tables in the database. If the relationship does not exist in the database, it does not exist in the Prisma schema. ### MongoDB For MongoDB, Prisma ORM currently uses a [normalized data model design](https://www.mongodb.com/docs/manual/data-modeling/), which means that documents reference each other by ID in a similar way to relational databases. The following document represents a `User` (in the `User` collection): ```json { "_id": { "$oid": "60d5922d00581b8f0062e3a8" }, "name": "Ella" } ``` The following list of `Post` documents (in the `Post` collection) each have a `authorId` field which reference the same user: ```json [ { "_id": { "$oid": "60d5922e00581b8f0062e3a9" }, "title": "How to make sushi", "authorId": { "$oid": "60d5922d00581b8f0062e3a8" } }, { "_id": { "$oid": "60d5922e00581b8f0062e3aa" }, "title": "How to re-install Windows", "authorId": { "$oid": "60d5922d00581b8f0062e3a8" } } ] ``` This data structure represents a one-to-many relation because multiple `Post` documents refer to the same `User` document. #### `@db.ObjectId` on IDs and relation scalar fields If your model's ID is an `ObjectId` (represented by a `String` field), you must add `@db.ObjectId` to the model's ID _and_ the relation scalar field on the other side of the relation: ```prisma highlight=3,9;normal model User { id String @id @default(auto()) @map("_id") @db.ObjectId //highlight-next-line posts Post[] } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId author User @relation(fields: [authorId], references: [id]) //highlight-next-line authorId String @db.ObjectId // relation scalar field (used in the `@relation` attribute above) title String } ``` ## Relations in Prisma Client Prisma Client is generated from the Prisma schema. The following examples demonstrate how relations manifest when you use Prisma Client to get, create, and update records. ### Create a record and nested records The following query creates a `User` record and two connected `Post` records: ```ts const userAndPosts = await prisma.user.create({ data: { posts: { create: [ { title: 'Prisma Day 2020' }, // Populates authorId with user's id { title: 'How to write a Prisma schema' }, // Populates authorId with user's id ], }, }, }) ``` In the underlying database, this query: 1. Creates a `User` with an auto-generated `id` (for example, `20`) 2. Creates two new `Post` records and sets the `authorId` of both records to `20` ### Retrieve a record and include related records The following query retrieves a `User` by `id` and includes any related `Post` records: ```ts const getAuthor = await prisma.user.findUnique({ where: { id: "20", }, include: { //highlight-next-line posts: true, // All posts where authorId == 20 }, }); ``` In the underlying database, this query: 1. Retrieves the `User` record with an `id` of `20` 2. Retrieves all `Post` records with an `authorId` of `20` ### Associate an existing record to another existing record The following query associates an existing `Post` record with an existing `User` record: ```ts const updateAuthor = await prisma.user.update({ where: { id: 20, }, data: { posts: { connect: { id: 4, }, }, }, }) ``` In the underlying database, this query uses a [nested `connect` query](/orm/reference/prisma-client-reference#connect) to link the post with an `id` of 4 to the user with an `id` of 20. The query does this with the following steps: - The query first looks for the user with an `id` of `20`. - The query then sets the `authorID` foreign key to `20`. This links the post with an `id` of `4` to the user with an `id` of `20`. In this query, the current value of `authorID` does not matter. The query changes `authorID` to `20`, no matter its current value. ## Types of relations There are three different types (or [cardinalities]()) of relations in Prisma ORM: - [One-to-one](/orm/prisma-schema/data-model/relations/one-to-one-relations) (also called 1-1 relations) - [One-to-many](/orm/prisma-schema/data-model/relations/one-to-many-relations) (also called 1-n relations) - [Many-to-many](/orm/prisma-schema/data-model/relations/many-to-many-relations) (also called m-n relations) The following Prisma schema includes every type of relation: - one-to-one: `User` ↔ `Profile` - one-to-many: `User` ↔ `Post` - many-to-many: `Post` ↔ `Category` ```prisma model User { id Int @id @default(autoincrement()) posts Post[] profile Profile? } model Profile { id Int @id @default(autoincrement()) user User @relation(fields: [userId], references: [id]) userId Int @unique // relation scalar field (used in the `@relation` attribute above) } model Post { id Int @id @default(autoincrement()) author User @relation(fields: [authorId], references: [id]) authorId Int // relation scalar field (used in the `@relation` attribute above) categories Category[] } model Category { id Int @id @default(autoincrement()) posts Post[] } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId posts Post[] profile Profile? } model Profile { id String @id @default(auto()) @map("_id") @db.ObjectId user User @relation(fields: [userId], references: [id]) userId String @unique @db.ObjectId // relation scalar field (used in the `@relation` attribute above) } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId // relation scalar field (used in the `@relation` attribute above) categories Category[] @relation(fields: [categoryIds], references: [id]) categoryIds String[] @db.ObjectId } model Category { id String @id @default(auto()) @map("_id") @db.ObjectId posts Post[] @relation(fields: [postIds], references: [id]) postIds String[] @db.ObjectId } ``` This schema is the same as the [example data model](/orm/prisma-schema/data-model/models) but has all [scalar fields](/orm/prisma-schema/data-model/models#scalar-fields) removed (except for the required [relation scalar fields](/orm/prisma-schema/data-model/relations#relation-scalar-fields)) so you can focus on the [relation fields](#relation-fields). This example uses [implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations). These relations do not require the `@relation` attribute unless you need to [disambiguate relations](#disambiguating-relations). Notice that the syntax is slightly different between relational databases and MongoDB - particularly for [many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations). For relational databases, the following entity relationship diagram represents the database that corresponds to the sample Prisma schema: ![The sample schema as an entity relationship diagram](./sample-schema.png) For MongoDB, Prisma ORM uses a [normalized data model design](https://www.mongodb.com/docs/manual/data-modeling/), which means that documents reference each other by ID in a similar way to relational databases. See [the MongoDB section](#mongodb) for more details. ### Implicit and explicit many-to-many relations Many-to-many relations in relational databases can be modelled in two ways: - [explicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#explicit-many-to-many-relations), where the relation table is represented as an explicit model in your Prisma schema - [implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations), where Prisma ORM manages the relation table and it does not appear in the Prisma schema. Implicit many-to-many relations require both models to have a single `@id`. Be aware of the following: - You cannot use a [multi-field ID](/orm/reference/prisma-schema-reference#id-1) - You cannot use a `@unique` in place of an `@id` To use either of these features, you must set up an explicit many-to-many instead. The implicit many-to-many relation still manifests in a relation table in the underlying database. However, Prisma ORM manages this relation table. If you use an implicit many-to-many relation instead of an explicit one, it makes the [Prisma Client API](/orm/prisma-client) simpler (because, for example, you have one fewer level of nesting inside of [nested writes](/orm/prisma-client/queries/relation-queries#nested-writes)). If you're not using Prisma Migrate but obtain your data model from [introspection](/orm/prisma-schema/introspection), you can still make use of implicit many-to-many relations by following Prisma ORM's [conventions for relation tables](/orm/prisma-schema/data-model/relations/many-to-many-relations#conventions-for-relation-tables-in-implicit-m-n-relations). ## Relation fields Relation [fields](/orm/prisma-schema/data-model/models#defining-fields) are fields on a Prisma [model](/orm/prisma-schema/data-model/models#defining-models) that do _not_ have a [scalar type](/orm/prisma-schema/data-model/models#scalar-fields). Instead, their type is another model. Every relation must have exactly two relation fields, one on each model. In the case of one-to-one and one-to-many relations, an additional _relation scalar field_ is required which gets linked by one of the two relation fields in the `@relation` attribute. This relation scalar field is the direct representation of the _foreign key_ in the underlying database. ```prisma model User { id Int @id @default(autoincrement()) email String @unique role Role @default(USER) posts Post[] // relation field (defined only at the Prisma ORM level) } model Post { id Int @id @default(autoincrement()) title String author User @relation(fields: [authorId], references: [id]) // relation field (uses the relation scalar field `authorId` below) authorId Int // relation scalar field (used in the `@relation` attribute above) } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique role Role @default(USER) posts Post[] // relation field (defined only at the Prisma ORM level) } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId title String author User @relation(fields: [authorId], references: [id]) // relation field (uses the relation scalar field `authorId` below) authorId String @db.ObjectId // relation scalar field (used in the `@relation` attribute above) } ``` Both `posts` and `author` are relation fields because their types are not scalar types but other models. Also note that the [annotated relation field](#annotated-relation-fields) `author` needs to link the relation scalar field `authorId` on the `Post` model inside the `@relation` attribute. The relation scalar field represents the foreign key in the underlying database. Both the relation fields (i.e. `posts` and `author`) are defined purely on a Prisma ORM-level, they don't manifest in the database. ### Annotated relation fields Relations that require one side of the relation to be _annotated_ with the `@relation` attribute are referred to as _annotated relation fields_. This includes: - one-to-one relations - one-to-many relations - many-to-many relations for MongoDB only The side of the relation which is annotated with the `@relation` attribute represents the side that **stores the foreign key in the underlying database**. The "actual" field that represents the foreign key is required on that side of the relation as well, it's called _relation scalar field_, and is referenced inside `@relation` attribute: ```prisma author User @relation(fields: [authorId], references: [id]) authorId Int ``` ```prisma author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId ``` A scalar field _becomes_ a relation scalar field when it's used in the `fields` of a `@relation` attribute. ### Relation scalar fields #### Relation scalar field naming conventions Because a relation scalar field always _belongs_ to a relation field, the following naming convention is common: - Relation field: `author` - Relation scalar field: `authorId` (relation field name + `Id`) ## The `@relation` attribute The [`@relation`](/orm/reference/prisma-schema-reference#relation) attribute can only be applied to the [relation fields](#relation-fields), not to [scalar fields](/orm/prisma-schema/data-model/models#scalar-fields). The `@relation` attribute is required when: - you define a one-to-one or one-to-many relation, it is required on _one side_ of the relation (with the corresponding relation scalar field) - you need to disambiguate a relation (that's e.g. the case when you have two relations between the same models) - you define a [self-relation](/orm/prisma-schema/data-model/relations/self-relations) - you define [a many-to-many relation for MongoDB](/orm/prisma-schema/data-model/relations/many-to-many-relations#mongodb) - you need to control how the relation table is represented in the underlying database (e.g. use a specific name for a relation table) > **Note**: [Implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations) in relational databases do not require the `@relation` attribute. ## Disambiguating relations When you define two relations between the same two models, you need to add the `name` argument in the `@relation` attribute to disambiguate them. As an example for why that's needed, consider the following models: ```prisma highlight=6,7,13,15;normal no-copy // NOTE: This schema is intentionally incorrect. See below for a working solution. model User { id Int @id @default(autoincrement()) name String? //highlight-start writtenPosts Post[] pinnedPost Post? //highlight-end } model Post { id Int @id @default(autoincrement()) title String? //highlight-next-line author User @relation(fields: [authorId], references: [id]) authorId Int //highlight-next-line pinnedBy User? @relation(fields: [pinnedById], references: [id]) pinnedById Int? } ``` ```prisma highlight=6,7,13,15;normal no-copy // NOTE: This schema is intentionally incorrect. See below for a working solution. model User { id String @id @default(auto()) @map("_id") @db.ObjectId name String? //highlight-start writtenPosts Post[] pinnedPost Post? //highlight-end } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId title String? //highlight-next-line author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId //highlight-next-line pinnedBy User? @relation(fields: [pinnedById], references: [id]) pinnedById String? @db.ObjectId } ``` In that case, the relations are ambiguous, there are four different ways to interpret them: - `User.writtenPosts` ↔ `Post.author` + `Post.authorId` - `User.writtenPosts` ↔ `Post.pinnedBy` + `Post.pinnedById` - `User.pinnedPost` ↔ `Post.author` + `Post.authorId` - `User.pinnedPost` ↔ `Post.pinnedBy` + `Post.pinnedById` To disambiguate these relations, you need to annotate the relation fields with the `@relation` attribute and provide the `name` argument. You can set any `name` (except for the empty string `""`), but it must be the same on both sides of the relation: ```prisma highlight=4,5,11,13;normal model User { id Int @id @default(autoincrement()) name String? //highlight-start writtenPosts Post[] @relation("WrittenPosts") pinnedPost Post? @relation("PinnedPost") //highlight-end } model Post { id Int @id @default(autoincrement()) title String? //highlight-next-line author User @relation("WrittenPosts", fields: [authorId], references: [id]) authorId Int //highlight-next-line pinnedBy User? @relation("PinnedPost", fields: [pinnedById], references: [id]) pinnedById Int? @unique } ``` ```prisma highlight=4,5,11,13;normal model User { id String @id @default(auto()) @map("_id") @db.ObjectId name String? //highlight-start writtenPosts Post[] @relation("WrittenPosts") pinnedPost Post? @relation("PinnedPost") //highlight-end } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId title String? //highlight-next-line author User @relation("WrittenPosts", fields: [authorId], references: [id]) authorId String @db.ObjectId //highlight-next-line pinnedBy User? @relation("PinnedPost", fields: [pinnedById], references: [id]) pinnedById String? @unique @db.ObjectId } ``` --- # Indexes URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/indexes Prisma ORM allows configuration of database indexes, unique constraints and primary key constraints. This is in General Availability in versions `4.0.0` and later. You can enable this with the `extendedIndexes` Preview feature in versions `3.5.0` and later. Version `3.6.0` also introduces support for introspection and migration of full text indexes in MySQL and MongoDB through a new `@@fulltext` attribute, available through the `fullTextIndex` Preview feature. If you are upgrading from a version earlier than 4.0.0, these changes to index configuration and full text indexes might be **breaking changes** if you have a database that already uses these features. See [Upgrading from previous versions](#upgrading-from-previous-versions) for more information on how to upgrade. ## Index configuration You can configure indexes, unique constraints, and primary key constraints with the following attribute arguments: - The [`length` argument](#configuring-the-length-of-indexes-with-length-mysql) allows you to specify a maximum length for the subpart of the value to be indexed on `String` and `Bytes` types - Available on the `@id`, `@@id`, `@unique`, `@@unique` and `@@index` attributes - MySQL only - The [`sort` argument](#configuring-the-index-sort-order-with-sort) allows you to specify the order that the entries of the constraint or index are stored in the database - Available on the `@unique`, `@@unique` and `@@index` attributes in all databases, and on the `@id` and `@@id` attributes in SQL Server - The [`type` argument](#configuring-the-access-type-of-indexes-with-type-postgresql) allows you to support index access methods other than PostgreSQL's default `BTree` access method - Available on the `@@index` attribute - PostgreSQL only - Supported index access methods: `Hash`, `Gist`, `Gin`, `SpGist` and `Brin` - The [`clustered` argument](#configuring-if-indexes-are-clustered-or-non-clustered-with-clustered-sql-server) allows you to configure whether a constraint or index is clustered or non-clustered - Available on the `@id`, `@@id`, `@unique`, `@@unique` and `@@index` attributes - SQL Server only See the linked sections for details of which version each feature was first introduced in. ### Configuring the length of indexes with `length` (MySQL) The `length` argument is specific to MySQL and allows you to define indexes and constraints on columns of `String` and `Byte` types. For these types, MySQL requires you to specify a maximum length for the subpart of the value to be indexed in cases where the full value would exceed MySQL's limits for index sizes. See [the MySQL documentation](https://dev.mysql.com/doc/refman/8.0/en/innodb-limits.html) for more details. The `length` argument is available on the `@id`, `@@id`, `@unique`, `@@unique` and `@@index` attributes. It is generally available in versions 4.0.0 and later, and available as part of the `extendedIndexes` preview feature in versions 3.5.0 and later. As an example, the following data model declares an `id` field with a maximum length of 3000 characters: ```prisma file=schema.prisma showLineNumbers model Id { id String @id @db.VarChar(3000) } ``` This is not valid in MySQL because it exceeds MySQL's index storage limit and therefore Prisma ORM rejects the data model. The generated SQL would be rejected by the database. ```sql CREATE TABLE `Id` ( `id` VARCHAR(3000) PRIMARY KEY ) ``` The `length` argument allows you to specify that only a subpart of the `id` value represents the primary key. In the example below, the first 100 characters are used: ```prisma file=schema.prisma showLineNumbers model Id { id String @id(length: 100) @db.VarChar(3000) } ``` Prisma Migrate is able to create constraints and indexes with the `length` argument if specified in your data model. This means that you can create indexes and constraints on values of Prisma schema type `Byte` and `String`. If you don't specify the argument the index is treated as covering the full value as before. Introspection will fetch these limits where they are present in your existing database. This allows Prisma ORM to support indexes and constraints that were previously suppressed and results in better support of MySQL databases utilizing this feature. The `length` argument can also be used on compound primary keys, using the `@@id` attribute, as in the example below: ```prisma file=schema.prisma showLineNumbers model CompoundId { id_1 String @db.VarChar(3000) id_2 String @db.VarChar(3000) @@id([id_1(length: 100), id_2(length: 10)]) } ``` A similar syntax can be used for the `@@unique` and `@@index` attributes. ### Configuring the index sort order with `sort` The `sort` argument is available for all databases supported by Prisma ORM. It allows you to specify the order that the entries of the index or constraint are stored in the database. This can have an effect on whether the database is able to use an index for specific queries. The `sort` argument is available for all databases on `@unique`, `@@unique` and `@@index`. Additionally, SQL Server also allows it on `@id` and `@@id`. It is generally available in versions 4.0.0 and later, and available as part of the `extendedIndexes` preview feature in versions 3.5.0 and later. As an example, the following table ```sql CREATE TABLE `Unique` ( `unique` INT, CONSTRAINT `Unique_unique_key` UNIQUE (`unique` DESC) ) ``` is now introspected as ```prisma file=schema.prisma showLineNumbers model Unique { unique Int @unique(sort: Desc) } ``` The `sort` argument can also be used on compound indexes: ```prisma file=schema.prisma showLineNumbers model CompoundUnique { unique_1 Int unique_2 Int @@unique([unique_1(sort: Desc), unique_2]) } ``` ### Example: using `sort` and `length` together The following example demonstrates the use of the `sort` and `length` arguments to configure indexes and constraints for a `Post` model: ```prisma file=schema.prisma showLineNumbers model Post { title String @db.VarChar(300) abstract String @db.VarChar(3000) slug String @unique(sort: Desc, length: 42) @db.VarChar(3000) author String created_at DateTime @@id([title(length: 100, sort: Desc), abstract(length: 10)]) @@index([author, created_at(sort: Desc)]) } ``` ### Configuring the access type of indexes with `type` (PostgreSQL) The `type` argument is available for configuring the index type in PostgreSQL with the `@@index` attribute. The index access methods available are `Hash`, `Gist`, `Gin`, `SpGist` and `Brin`, as well as the default `BTree` index access method. The `type` argument is generally available in versions 4.0.0 and later. The `Hash` index access method is available as part of the `extendedIndexes` preview feature in versions 3.6.0 and later, and the `Gist`, `Gin`, `SpGist` and `Brin` index access methods are available in preview in versions 3.14.0 and later. #### Hash The `Hash` type will store the index data in a format that is much faster to search and insert, and that will use less disk space. However, only the `=` and `<>` comparisons can use the index, so other comparison operators such as `<` and `>` will be much slower with `Hash` than when using the default `BTree` type. As an example, the following model adds an index with a `type` of `Hash` to the `value` field: ```prisma file=schema.prisma showLineNumbers model Example { id Int @id value Int @@index([value], type: Hash) } ``` This translates to the following SQL commands: ```sql CREATE TABLE "Example" ( id INT PRIMARY KEY, value INT NOT NULL ); CREATE INDEX "Example_value_idx" ON "Example" USING HASH (value); ``` #### Generalized Inverted Index (GIN) The GIN index stores composite values, such as arrays or `JsonB` data. This is useful for speeding up querying whether one object is part of another object. It is commonly used for full-text searches. An indexed field can define the operator class, which defines the operators handled by the index. Indexes using a function (such as `to_tsvector`) to determine the indexed value are not yet supported by Prisma ORM. Indexes defined in this way will not be visible with `prisma db pull`. As an example, the following model adds a `Gin` index to the `value` field, with `JsonbPathOps` as the class of operators allowed to use the index: ```prisma file=schema.prisma showLineNumbers model Example { id Int @id value Json // ^ field type matching the operator class // ^ operator class ^ index type @@index([value(ops: JsonbPathOps)], type: Gin) } ``` This translates to the following SQL commands: ```sql CREATE TABLE "Example" ( id INT PRIMARY KEY, value JSONB NOT NULL ); CREATE INDEX "Example_value_idx" ON "Example" USING GIN (value jsonb_path_ops); ``` As part of the `JsonbPathOps` the `@>` operator is handled by the index, speeding up queries such as `value @> '{"foo": 2}'`. ##### Supported Operator Classes for GIN Prisma ORM generally supports operator classes provided by PostgreSQL in versions 10 and later. If the operator class requires the field type to be of a type Prisma ORM does not yet support, using the `raw` function with a string input allows you to use these operator classes without validation. The default operator class (marked with ✅) can be omitted from the index definition. | Operator class | Allowed field type (native types) | Default | Other | | -------------- | --------------------------------- | ------- | ----------------------------- | | `ArrayOps` | Any array | ✅ | Also available in CockroachDB | | `JsonbOps` | `Json` (`@db.JsonB`) | ✅ | Also available in CockroachDB | | `JsonbPathOps` | `Json` (`@db.JsonB`) | | | | `raw("other")` | | | | Read more about built-in operator classes in the [official PostgreSQL documentation](https://www.postgresql.org/docs/14/gin-builtin-opclasses.html). ##### CockroachDB GIN and BTree are the only index types supported by CockroachDB. The operator classes marked to work with CockroachDB are the only ones allowed on that database and supported by Prisma ORM. The operator class cannot be defined in the Prisma Schema Language: the `ops` argument is not necessary or allowed on CockroachDB. #### Generalized Search Tree (GiST) The GiST index type is used for implementing indexing schemes for user-defined types. By default there are not many direct uses for GiST indexes, but for example the B-Tree index type is built using a GiST index. As an example, the following model adds a `Gist` index to the `value` field with `InetOps` as the operators that will be using the index: ```prisma file=schema.prisma showLineNumbers model Example { id Int @id value String @db.Inet // ^ native type matching the operator class // ^ index type // ^ operator class @@index([value(ops: InetOps)], type: Gist) } ``` This translates to the following SQL commands: ```sql CREATE TABLE "Example" ( id INT PRIMARY KEY, value INET NOT NULL ); CREATE INDEX "Example_value_idx" ON "Example" USING GIST (value inet_ops); ``` Queries comparing IP addresses, such as `value > '10.0.0.2'`, will use the index. ##### Supported Operator Classes for GiST Prisma ORM generally supports operator classes provided by PostgreSQL in versions 10 and later. If the operator class requires the field type to be of a type Prisma ORM does not yet support, using the `raw` function with a string input allows you to use these operator classes without validation. | Operator class | Allowed field type (allowed native types) | | -------------- | ----------------------------------------- | | `InetOps` | `String` (`@db.Inet`) | | `raw("other")` | | Read more about built-in operator classes in the [official PostgreSQL documentation](https://www.postgresql.org/docs/14/gist-builtin-opclasses.html). #### Space-Partitioned GiST (SP-GiST) The SP-GiST index is a good choice for many different non-balanced data structures. If the query matches the partitioning rule, it can be very fast. As with GiST, SP-GiST is important as a building block for user-defined types, allowing implementation of custom search operators directly with the database. As an example, the following model adds a `SpGist` index to the `value` field with `TextOps` as the operators using the index: ```prisma file=schema.prisma showLineNumbers model Example { id Int @id value String // ^ field type matching the operator class @@index([value], type: SpGist) // ^ index type // ^ using the default ops: TextOps } ``` This translates to the following SQL commands: ```sql CREATE TABLE "Example" ( id INT PRIMARY KEY, value TEXT NOT NULL ); CREATE INDEX "Example_value_idx" ON "Example" USING SPGIST (value); ``` Queries such as `value LIKE 'something%'` will be sped up by the index. ##### Supported Operator Classes for SP-GiST Prisma ORM generally supports operator classes provided by PostgreSQL in versions 10 and later. If the operator class requires the field type to be of a type Prisma ORM does not yet support, using the `raw` function with a string input allows you to use these operator classes without validation. The default operator class (marked with ✅) can be omitted from the index definition. | Operator class | Allowed field type (native types) | Default | Supported PostgreSQL versions | | -------------- | ------------------------------------ | ------- | ----------------------------- | | `InetOps` | `String` (`@db.Inet`) | ✅ | 10+ | | `TextOps` | `String` (`@db.Text`, `@db.VarChar`) | ✅ | | | `raw("other")` | | | | Read more about built-in operator classes from [official PostgreSQL documentation](https://www.postgresql.org/docs/14/spgist-builtin-opclasses.html). #### Block Range Index (BRIN) The BRIN index type is useful if you have lots of data that does not change after it is inserted, such as date and time values. If your data is a good fit for the index, it can store large datasets in a minimal space. As an example, the following model adds a `Brin` index to the `value` field with `Int4BloomOps` as the operators that will be using the index: ```prisma file=schema.prisma showLineNumbers model Example { id Int @id value Int // ^ field type matching the operator class // ^ operator class ^ index type @@index([value(ops: Int4BloomOps)], type: Brin) } ``` This translates to the following SQL commands: ```sql CREATE TABLE "Example" ( id INT PRIMARY KEY, value INT4 NOT NULL ); CREATE INDEX "Example_value_idx" ON "Example" USING BRIN (value int4_bloom_ops); ``` Queries like `value = 2` will now use the index, which uses a fraction of the space used by the `BTree` or `Hash` indexes. ##### Supported Operator Classes for BRIN Prisma ORM generally supports operator classes provided by PostgreSQL in versions 10 and later, and some supported operators are only available from PostgreSQL versions 14 and later. If the operator class requires the field type to be of a type Prisma ORM does not yet support, using the `raw` function with a string input allows you to use these operator classes without validation. The default operator class (marked with ✅) can be omitted from the index definition. | Operator class | Allowed field type (native types) | Default | Supported PostgreSQL versions | | --------------------------- | ------------------------------------ | ------- | ----------------------------- | | `BitMinMaxOps` | `String` (`@db.Bit`) | ✅ | | | `VarBitMinMaxOps` | `String` (`@db.VarBit`) | ✅ | | | `BpcharBloomOps` | `String` (`@db.Char`) | | 14+ | | `BpcharMinMaxOps` | `String` (`@db.Char`) | ✅ | | | `ByteaBloomOps` | `Bytes` (`@db.Bytea`) | | 14+ | | `ByteaMinMaxOps` | `Bytes` (`@db.Bytea`) | ✅ | | | `DateBloomOps` | `DateTime` (`@db.Date`) | | 14+ | | `DateMinMaxOps` | `DateTime` (`@db.Date`) | ✅ | | | `DateMinMaxMultiOps` | `DateTime` (`@db.Date`) | | 14+ | | `Float4BloomOps` | `Float` (`@db.Real`) | | 14+ | | `Float4MinMaxOps` | `Float` (`@db.Real`) | ✅ | | | `Float4MinMaxMultiOps` | `Float` (`@db.Real`) | | 14+ | | `Float8BloomOps` | `Float` (`@db.DoublePrecision`) | | 14+ | | `Float8MinMaxOps` | `Float` (`@db.DoublePrecision`) | ✅ | | | `Float8MinMaxMultiOps` | `Float` (`@db.DoublePrecision`) | | 14+ | | `InetInclusionOps` | `String` (`@db.Inet`) | ✅ | 14+ | | `InetBloomOps` | `String` (`@db.Inet`) | | 14+ | | `InetMinMaxOps` | `String` (`@db.Inet`) | | | | `InetMinMaxMultiOps` | `String` (`@db.Inet`) | | 14+ | | `Int2BloomOps` | `Int` (`@db.SmallInt`) | | 14+ | | `Int2MinMaxOps` | `Int` (`@db.SmallInt`) | ✅ | | | `Int2MinMaxMultiOps` | `Int` (`@db.SmallInt`) | | 14+ | | `Int4BloomOps` | `Int` (`@db.Integer`) | | 14+ | | `Int4MinMaxOps` | `Int` (`@db.Integer`) | ✅ | | | `Int4MinMaxMultiOps` | `Int` (`@db.Integer`) | | 14+ | | `Int8BloomOps` | `BigInt` (`@db.BigInt`) | | 14+ | | `Int8MinMaxOps` | `BigInt` (`@db.BigInt`) | ✅ | | | `Int8MinMaxMultiOps` | `BigInt` (`@db.BigInt`) | | 14+ | | `NumericBloomOps` | `Decimal` (`@db.Decimal`) | | 14+ | | `NumericMinMaxOps` | `Decimal` (`@db.Decimal`) | ✅ | | | `NumericMinMaxMultiOps` | `Decimal` (`@db.Decimal`) | | 14+ | | `OidBloomOps` | `Int` (`@db.Oid`) | | 14+ | | `OidMinMaxOps` | `Int` (`@db.Oid`) | ✅ | | | `OidMinMaxMultiOps` | `Int` (`@db.Oid`) | | 14+ | | `TextBloomOps` | `String` (`@db.Text`, `@db.VarChar`) | | 14+ | | `TextMinMaxOps` | `String` (`@db.Text`, `@db.VarChar`) | ✅ | | | `TextMinMaxMultiOps` | `String` (`@db.Text`, `@db.VarChar`) | | 14+ | | `TimestampBloomOps` | `DateTime` (`@db.Timestamp`) | | 14+ | | `TimestampMinMaxOps` | `DateTime` (`@db.Timestamp`) | ✅ | | | `TimestampMinMaxMultiOps` | `DateTime` (`@db.Timestamp`) | | 14+ | | `TimestampTzBloomOps` | `DateTime` (`@db.Timestamptz`) | | 14+ | | `TimestampTzMinMaxOps` | `DateTime` (`@db.Timestamptz`) | ✅ | | | `TimestampTzMinMaxMultiOps` | `DateTime` (`@db.Timestamptz`) | | 14+ | | `TimeBloomOps` | `DateTime` (`@db.Time`) | | 14+ | | `TimeMinMaxOps` | `DateTime` (`@db.Time`) | ✅ | | | `TimeMinMaxMultiOps` | `DateTime` (`@db.Time`) | | 14+ | | `TimeTzBloomOps` | `DateTime` (`@db.Timetz`) | | 14+ | | `TimeTzMinMaxOps` | `DateTime` (`@db.Timetz`) | ✅ | | | `TimeTzMinMaxMultiOps` | `DateTime` (`@db.Timetz`) | | 14+ | | `UuidBloomOps` | `String` (`@db.Uuid`) | | 14+ | | `UuidMinMaxOps` | `String` (`@db.Uuid`) | ✅ | | | `UuidMinMaxMultiOps` | `String` (`@db.Uuid`) | | 14+ | | `raw("other")` | | | | Read more about built-in operator classes in the [official PostgreSQL documentation](https://www.postgresql.org/docs/14/brin-builtin-opclasses.html). ### Configuring if indexes are clustered or non-clustered with `clustered` (SQL Server) The `clustered` argument is available to configure (non)clustered indexes in SQL Server. It can be used on the `@id`, `@@id`, `@unique`, `@@unique` and `@@index` attributes. It is generally available in versions 4.0.0 and later, and available as part of the `extendedIndexes` preview feature in versions 3.13.0 and later. As an example, the following model configures the `@id` to be non-clustered (instead of the clustered default): ```prisma file=schema.prisma showLineNumbers model Example { id Int @id(clustered: false) value Int } ``` This translates to the following SQL commands: ```sql CREATE TABLE [Example] ( id INT NOT NULL, value INT, CONSTRAINT [Example_pkey] PRIMARY KEY NONCLUSTERED (id) ) ``` The default value of `clustered` for each attribute is as follows: | Attribute | Value | | ---------- | ------- | | `@id` | `true` | | `@@id` | `true` | | `@unique` | `false` | | `@@unique` | `false` | | `@@index` | `false` | A table can have at most one clustered index. ### Upgrading from previous versions These index configuration changes can be **breaking changes** when activating the functionality for certain, existing Prisma schemas for existing databases. After enabling the preview features required to use them, run `prisma db pull` to introspect the existing database to update your Prisma schema before using Prisma Migrate again. A breaking change can occur in the following situations: - **Existing sort constraints and indexes:** earlier versions of Prisma ORM will assume that the desired sort order is _ascending_ if no order is specified explicitly. This means that this is a breaking change if you have existing constraints or indexes that are using descending sort order and migrate your database without first specifying this in your data model. - **Existing length constraints and indexes:** in earlier versions of Prisma ORM, indexes and constraints that were length constrained in MySQL could not be represented in the Prisma schema. Therefore `prisma db pull` was not fetching these and you could not manually specify them. When you ran `prisma db push` or `prisma migrate dev` they were ignored if already present in your database. Since you are now able to specify these, migrate commands will now drop them if they are missing from your data model but present in the database. - **Existing indexes other than `BTree` (PostgreSQL):** earlier versions of Prisma ORM only supported the default `BTree` index type. Other supported indexes (`Hash`, `Gist`, `Gin`, `SpGist` and `Brin`) need to be added before migrating your database. - **Existing (non-)clustered indexes (SQL Server):** earlier versions of Prisma ORM did not support configuring an index as clustered or non-clustered. For indexes that do not use the default, these need to be added before migrating your database. In each of the cases above unwanted changes to your database can be prevented by properly specifying these properties in your data model where necessary. **The easiest way to do this is to use `prisma db pull` to retrieve any existing constraints or configuration.** Alternatively, you could also add these arguments manually. This should be done before using `prisma db push` or `prisma migrate dev` the first time after the upgrade. ## Full text indexes (MySQL and MongoDB) The `fullTextIndex` preview feature provides support for introspection and migration of full text indexes in MySQL and MongoDB in version 3.6.0 and later. This can be configured using the `@@fulltext` attribute. Existing full text indexes in the database are added to your Prisma schema after introspecting with `db pull`, and new full text indexes added in the Prisma schema are created in the database when using Prisma Migrate. This also prevents validation errors in some database schemas that were not working before. For now we do not enable the full text search commands in Prisma Client for MongoDB; the progress can be followed in the [MongoDB](https://github.com/prisma/prisma/issues/9413) issue. ### Enabling the `fullTextIndex` preview feature To enable the `fullTextIndex` preview feature, add the `fullTextIndex` feature flag to the `generator` block of the `schema.prisma` file: ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" previewFeatures = ["fullTextIndex"] } ``` ### Examples The following example demonstrates adding a `@@fulltext` index to the `title` and `content` fields of a `Post` model: ```prisma file=schema.prisma showLineNumbers model Post { id Int @id title String @db.VarChar(255) content String @db.Text @@fulltext([title, content]) } ``` On MongoDB, you can use the `@@fulltext` index attribute (via the `fullTextIndex` preview feature) with the `sort` argument to add fields to your full-text index in ascending or descending order. The following example adds a `@@fulltext` index to the `title` and `content` fields of the `Post` model, and sorts the `title` field in descending order: ```prisma file=schema.prisma showLineNumbers generator js { provider = "prisma-client-js" previewFeatures = ["fullTextIndex"] } datasource db { provider = "mongodb" url = env("DATABASE_URL") } model Post { id String @id @map("_id") @db.ObjectId title String content String @@fulltext([title(sort: Desc), content]) } ``` ### Upgrading from previous versions This can be a **breaking change** when activating the functionality for certain, existing Prisma schemas for existing databases. After enabling the preview features required to use them, run `prisma db pull` to introspect the existing database to update your Prisma schema before using Prisma Migrate again. Earlier versions of Prisma ORM converted full text indexes using the `@@index` attribute rather than the `@@fulltext` attribute. After enabling the `fullTextIndex` preview feature, run `prisma db pull` to convert these indexes to `@@fulltext` before migrating again with Prisma Migrate. If you do not do this, the existing indexes will be dropped instead and normal indexes will be created in their place. --- # Views URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/views Support for views is currently a very early [Preview](/orm/more/releases#preview) feature. You can add a view to your Prisma schema with the `view` keyword or introspect the views in your database schema with `db pull`. You cannot yet apply views in your schema to your database with Prisma Migrate and `db push` unless the changes are added manually to your migration file using the `--create-only` flag.

For updates on progress with this feature, follow [our GitHub issue](https://github.com/prisma/prisma/issues/17335).
Database views allow you to name and store queries. In relational databases, views are [stored SQL queries](https://www.postgresql.org/docs/current/sql-createview.html) that might include columns in multiple tables, or calculated values such as aggregates. In MongoDB, views are queryable objects where the contents are defined by an [aggregation pipeline](https://www.mongodb.com/docs/manual/core/aggregation-pipeline) on other collections. The `views` preview feature allows you to represent views in your Prisma schema with the `view` keyword. To use views in Prisma ORM, follow these steps: - [Enable the `views` preview feature](#enable-the-views-preview-feature) - [Create a view in the underlying database](#create-a-view-in-the-underlying-database), either directly or as a [manual addition to a Prisma Migrate migration file](#use-views-with-prisma-migrate-and-db-push), or use an existing view - [Represent the view in your Prisma schema](#add-views-to-your-prisma-schema) - [Query the view in Prisma Client](#query-views-in-prisma-client)
## Enable the `views` preview feature Support for views is currently in an early preview. To enable the `views` preview feature, add the `views` feature flag to the `previewFeatures` field of the `generator` block in your Prisma Schema: ```prisma file=schema.prisma highlight=3;add showLineNumbers generator client { provider = "prisma-client-js" //add-next-line previewFeatures = ["views"] } ``` Please leave feedback about this preview feature in our dedicated [preview feature feedback issue for `views`](https://github.com/prisma/prisma/issues/17335). ## Create a view in the underlying database Currently, you cannot apply views that you define in your Prisma schema to your database with Prisma Migrate and `db push`. Instead, you must first create the view in the underlying database, either manually or [as part of a migration](#use-views-with-prisma-migrate-and-db-push). For example, take the following Prisma schema with a `User` model and a related `Profile` model: ```prisma model User { id Int @id @default(autoincrement()) email String @unique name String? profile Profile? } model Profile { id Int @id @default(autoincrement()) bio String user User @relation(fields: [userId], references: [id]) userId Int @unique } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique name String? profile Profile? } model Profile { id String @id @default(auto()) @map("_id") @db.ObjectId bio String User User @relation(fields: [userId], references: [id]) userId String @unique @db.ObjectId } ``` Next, take a `UserInfo` view in the underlying database that combines the `email` and `name` fields from the `User` model and the `bio` field from the `Profile` model. For a relational database, the SQL statement to create this view is: ```sql CREATE VIEW "UserInfo" AS SELECT u.id, email, name, bio FROM "User" u LEFT JOIN "Profile" p ON u.id = p."userId"; ``` For MongoDB, you can [create a view](https://www.mongodb.com/docs/manual/core/views/join-collections-with-view/) with the following command: ```ts db.createView('UserInfo', 'User', [ { $lookup: { from: 'Profile', localField: '_id', foreignField: 'userId', as: 'ProfileData', }, }, { $project: { _id: 1, email: 1, name: 1, bio: '$ProfileData.bio', }, }, { $unwind: '$bio' }, ]) ``` ## Use views with Prisma Migrate and `db push` If you apply changes to your Prisma schema with Prisma Migrate or `db push`, Prisma ORM does not create or run any SQL related to views. To include views in a migration, run `migrate dev --create-only` and then manually add the SQL for views to your migration file. Alternatively, you can create views manually in the database. ## Add views to your Prisma schema To add a view to your Prisma schema, use the `view` keyword. You can represent the `UserInfo` view from the example above in your Prisma schema as follows: ```prisma view UserInfo { id Int @unique email String name String bio String } ``` ```prisma view UserInfo { id String @id @default(auto()) @map("_id") @db.ObjectId email String name String bio String } ``` ### Write by hand A `view` block is comprised of two main pieces: - The `view` block definition - The view's field definitions These two pieces allow you to define the name of your view in the generated Prisma Client and the columns present in your view's query results. #### Define a `view` block To define the `UserInfo` view from the example above, begin by using the `view` keyword to define a `view` block in your schema named `UserInfo`: ```prisma view UserInfo { // Fields } ``` #### Define fields The properties of a view are called _fields_, which consist of: - A field name - A field type The fields of the `UserInfo` example view can be defined as follows: ```prisma highlight=2-5;normal view UserInfo { //highlight-start id Int @unique email String name String bio String //highlight-end } ``` ```prisma highlight=2-5;normal view UserInfo { //highlight-start id String @id @default(auto()) @map("_id") @db.ObjectId email String name String bio String //highlight-end } ``` Each _field_ of a `view` block represents a column in the query results of the view in the underlying database. ### Use introspection Currently only available for PostgreSQL, MySQL, SQL Server and CockroachDB. If you have an existing view or views defined in your database, [introspection](/orm/prisma-schema/introspection) will automatically generate `view` blocks in your Prisma schema that represent those views. Assuming the example `UserInfo` view exists in your underlying database, running the following command will generate a `view` block in your Prisma schema representing that view: ```terminal copy npx prisma db pull ``` The resulting `view` block will be defined as follows: ```prisma /// The underlying view does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client. view UserInfo { id Int? email String? name String? bio String? @@ignore } ``` The `view` block is generated initially with a `@@ignore` attribute because [there is no unique identifier defined](#unique-identifier) (which is currently a [limitation](#unique-identifier) of the views preview feature). Please note for now `db pull` will only introspect views in your schema when using PostgreSQL, MySQL, SQL Server or CockroachDB. Support for this workflow will be extended to other database providers. #### Adding a unique identifier to an introspected view To be able to use the introspected view in Prisma Client, you will need to select and define one or multiple of the fields as the unique identifier. In the above view's case, the `id` column refers to a uniquely identifiable field in the underlying `User` table so that field can also be used as the uniquely identifiable field in the `view` block. In order to make this `view` block valid you will need to: - Remove the _optional_ flag `?` from the `id` field - Add the `@unique` attribute to the `id` field - Remove the `@@ignore` attribute - Remove the generated comment warning about an invalid view ```prisma highlight=4;add|1,3,8,9;delete //delete-next-line /// The underlying view does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client. view UserInfo { //delete-next-line id Int? //add-next-line id Int @unique email String? name String? bio String? //delete-start @@ignore //delete-end } ``` When re-introspecting your database, any custom changes to your view definitions will be preserved. #### The `views` directory Introspection of a database with one or more existing views will also create a new `views` directory within your `prisma` directory (starting with Prisma version 4.12.0). This directory will contain a subdirectory named after your database's schema which contains a `.sql` file for each view that was introspected in that schema. Each file will be named after an individual view and will contain the query the related view defines. For example, after introspecting a database with the default `public` schema using the model used above you will find a `prisma/views/public/UserInfo.sql` file was created with the following contents: ```sql SELECT u.id, u.email, u.name, p.bio FROM ( "User" u LEFT JOIN "Profile" p ON ((u.id = p."userId")) ); ``` ### Limitations #### Unique Identifier Currently, Prisma ORM treats views in the same way as models. This means that a view needs to have at least one _unique identifier_, which can be represented by any of the following: - A unique constraint denoted with [`@unique`](/orm/prisma-schema/data-model/models#defining-a-unique-field) - A composite unique constraint denoted with [`@@unique`](/orm/prisma-schema/data-model/models#defining-a-unique-field) - An [`@id`](/orm/prisma-schema/data-model/models#defining-an-id-field) field - A composite identifier denoted with [`@@id`](/orm/prisma-schema/data-model/models#composite-ids) In relational databases, a view's unique identifier can be defined as a `@unique` attribute on one field, or a `@@unique` attribute on multiple fields. When possible, it is preferable to use a `@unique` or `@@unique` constraint over an `@id` or `@@id` field. In MongoDB, however, the unique identifier must be an `@id` attribute that maps to the `_id` field in the underlying database with `@map("_id")`. In the example above, the `id` field has a `@unique` attribute. If another column in the underlying `User` table had been defined as uniquely identifiable and made available in the view's query results, that column could have been used as the unique identifier instead. #### Introspection Currently, introspection of views is only available for PostgreSQL, MySQL, SQL Server and CockroachDB. If you are using another database provider, your views must be added manually. This is a temporary limitation and support for introspection will be extended to the other supported datasource providers. ## Query views in Prisma Client You can query views in Prisma Client in the same way that you query models. For example, the following query finds all users with a `name` of `'Alice'` in the `UserInfo` view defined above. ```ts const userinfo = await prisma.userInfo.findMany({ where: { name: 'Alice', }, }) ``` Currently, Prisma Client allows you to update a view if the underlying database allows it, without any additional validation. ## Special types of views This section describes how to use Prisma ORM with updatable and materialized views in your database. ### Updatable views Some databases support updatable views (e.g. [PostgreSQL](https://www.postgresql.org/docs/current/sql-createview.html#SQL-CREATEVIEW-UPDATABLE-VIEWS), [MySQL](https://dev.mysql.com/doc/refman/8.0/en/view-updatability.html) and [SQL Server](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-view-transact-sql?view=sql-server-ver16#updatable-views)). Updatable views allow you to create, update or delete entries. Currently Prisma ORM treats all `view`s as updatable views. If the underlying database supports this functionality for the view, the operation should succeed. If the view is not marked as updatable, the database will return an error, and Prisma Client will then throw this error. In the future, Prisma Client might support marking individual views as updatable or not updatable. Please comment on our [`views` feedback issue](https://github.com/prisma/prisma/issues/17335) with your use case. ### Materialized views Some databases support materialized views, e.g. [PostgreSQL](https://www.postgresql.org/docs/current/rules-materializedviews.html), [CockroachDB](https://www.cockroachlabs.com/docs/stable/views.html#materialized-views), [MongoDB](https://www.mongodb.com/docs/manual/core/materialized-views/), and [SQL Server](https://learn.microsoft.com/en-us/sql/relational-databases/views/create-indexed-views?view=sql-server-ver16) (where they're called "indexed views"). Materialized views persist the result of the view query for faster access and only update it on demand. Currently, Prisma ORM does not support materialized views. However, when you [manually create a view](#create-a-view-in-the-underlying-database), you can also create a materialized view with the corresponding command in the underlying database. You can then use Prisma Client's [TypedSQL functionality](/orm/prisma-client/using-raw-sql) to execute the command and refresh the view manually. In the future Prisma Client might support marking individual views as materialized and add a Prisma Client method to refresh the materialized view. Please comment on our [`views` feedback issue](https://github.com/prisma/prisma/issues/17335) with your use case. --- # Database mapping URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/database-mapping The [Prisma schema](/orm/prisma-schema) includes mechanisms that allow you to define names of certain database objects. You can: - [Map model and field names to different collection/table and field/column names](#mapping-collectiontable-and-fieldcolumn-names) - [Define constraint and index names](#constraint-and-index-names) ## Mapping collection/table and field/column names Sometimes the names used to describe entities in your database might not match the names you would prefer in your generated API. Mapping names in the Prisma schema allows you to influence the naming in your Client API without having to change the underlying database names. A common approach for naming tables/collections in databases for example is to use plural form and [snake_case](https://en.wikipedia.org/wiki/Snake_case) notation. However, we recommended a different [naming convention (singular form, PascalCase)](/orm/reference/prisma-schema-reference#naming-conventions). `@map` and `@@map` allow you to [tune the shape of your Prisma Client API](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) by decoupling model and field names from table and column names in the underlying database. ### Map collection / table names As an example, when you [introspect](/orm/prisma-schema/introspection) a database with a table named `comments`, the resulting Prisma model will look like this: ```prisma model comments { // Fields } ``` However, you can still choose `Comment` as the name of the model (e.g. to follow the naming convention) without renaming the underlying `comments` table in the database by using the [`@@map`](/orm/reference/prisma-schema-reference#map-1) attribute: ```prisma highlight=4;normal model Comment { // Fields //highlight-next-line @@map("comments") } ``` With this modified model definition, Prisma Client automatically maps the `Comment` model to the `comments` table in the underlying database. ### Map field / column names You can also [`@map`](/orm/reference/prisma-schema-reference#map) a column/field name: ```prisma highlight=2-4;normal model Comment { //highlight-start content String @map("comment_text") email String @map("commenter_email") type Enum @map("comment_type") //highlight-end @@map("comments") } ``` This way the `comment_text` column is not available under `prisma.comment.comment_text` in the Prisma Client API, but can be accessed via `prisma.comment.content`. ### Map enum names and values You can also `@map` an enum value, or `@@map` an enum: ```prisma highlight=3,5;normal enum Type { Blog, //highlight-next-line Twitter @map("comment_twitter") //highlight-next-line @@map("comment_source_enum") } ``` ## Constraint and index names You can optionally use the `map` argument to explicitly define the **underlying constraint and index names** in the Prisma schema for the attributes [`@id`](/orm/reference/prisma-schema-reference#id), [`@@id`](/orm/reference/prisma-schema-reference#id-1), [`@unique`](/orm/reference/prisma-schema-reference#unique), [`@@unique`](/orm/reference/prisma-schema-reference#unique-1), [`@@index`](/orm/reference/prisma-schema-reference#index) and [`@relation`](/orm/reference/prisma-schema-reference#relation). (This is available in Prisma ORM version [2.29.0](https://github.com/prisma/prisma/releases/tag/2.29.0) and later.) When introspecting a database, the `map` argument will _only_ be rendered in the schema if the name _differs_ from Prisma ORM's [default constraint naming convention for indexes and constraints](#prisma-orms-default-naming-conventions-for-indexes-and-constraints). If you use Prisma Migrate in a version earlier than 2.29.0 and want to maintain your existing constraint and index names after upgrading to a newer version, **do not** immediately run `prisma migrate` or `prisma db push`. This will **change any underlying constraint name that does not follow Prisma ORM's convention**. Follow the [upgrade path that allows you to maintain existing constraint and index names](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/named-constraints#option-1-i-want-to-maintain-my-existing-constraint-and-index-names). ### Use cases for named constraints Some use cases for explicitly named constraints include: - Company policy - Conventions of other tools ### Prisma ORM's default naming conventions for indexes and constraints Prisma ORM naming convention was chosen to align with PostgreSQL since it is deterministic. It also helps to maximize the amount of times where names do not need to be rendered because many databases out there they already align with the convention. Prisma ORM always uses the database names of entities when generating the default index and constraint names. If a model is remapped to a different name in the data model via `@@map` or `@map`, the default name generation will still take the name of the _table_ in the database as input. The same is true for fields and _columns_. | Entity | Convention | Example | | ----------------- | --------------------------------- | ------------------------------ | | Primary Key | \{tablename}\_pkey | `User_pkey` | | Unique Constraint | \{tablename}\_\{column_names}\_key | `User_firstName_last_Name_key` | | Non-Unique Index | \{tablename}\_\{column_names}\_idx | `User_age_idx` | | Foreign Key | \{tablename}\_\{column_names}\_fkey | `User_childName_fkey` | Since most databases have a length limit for entity names, the names will be trimmed if necessary to not violate the database limits. We will shorten the part before the `_suffix` as necessary so that the full name is at most the maximum length permitted. ### Using default constraint names When no explicit names are provided via `map` arguments Prisma ORM will generate index and constraint names following the [default naming convention](#prisma-orms-default-naming-conventions-for-indexes-and-constraints). If you introspect a database the names for indexes and constraints will be added to your schema unless they follow Prisma ORM's naming convention. If they do, the names are not rendered to keep the schema more readable. When you migrate such a schema Prisma will infer the default names and persist them in the database. #### Example The following schema defines three constraints (`@id`, `@unique`, and `@relation`) and one index (`@@index`): ```prisma highlight=2,8,11,13;normal model User { //highlight-next-line id Int @id @default(autoincrement()) name String @unique posts Post[] } model Post { //highlight-next-line id Int @id @default(autoincrement()) title String authorName String @default("Anonymous") //highlight-next-line author User? @relation(fields: [authorName], references: [name]) //highlight-next-line @@index([title, authorName]) } ``` Since no explicit names are provided via `map` arguments Prisma will assume they follow our default naming convention. The following table lists the name of each constraint and index in the underlying database: | Constraint or index | Follows convention | Underlying constraint or index names | | ---------------------------------- | ------------------ | ------------------------------------ | | `@id` (on `User` > `id` field) | Yes | `User_pk` | | `@@index` (on `Post`) | Yes | `Post_title_authorName_idx` | | `@id` (on `Post` > `id` field) | Yes | `Post_pk` | | `@relation` (on `Post` > `author`) | Yes | `Post_authorName_fkey` | ### Using custom constraint / index names You can use the `map` argument to define **custom constraint and index names** in the underlying database. #### Example The following example adds custom names to one `@id` and the `@@index`: ```prisma highlight=2,13;normal model User { //highlight-next-line id Int @id(map: "Custom_Primary_Key_Constraint_Name") @default(autoincrement()) name String @unique posts Post[] } model Post { //highlight-next-line id Int @id @default(autoincrement()) title String authorName String @default("Anonymous") //highlight-next-line author User? @relation(fields: [authorName], references: [name]) //highlight-next-line @@index([title, authorName], map: "My_Custom_Index_Name") } ``` The following table lists the name of each constraint and index in the underlying database: | Constraint or index | Follows convention | Underlying constraint or index names | | ---------------------------------- | ------------------ | ------------------------------------ | | `@id` (on `User` > `id` field) | No | `Custom_Primary_Key_Constraint_Name` | | `@@index` (on `Post`) | No | `My_Custom_Index_Name` | | `@id` (on `Post` > `id` field) | Yes | `Post_pk` | | `@relation` (on `Post` > `author`) | Yes | `Post_authorName_fkey` | ### Related: Naming indexes and primary keys for Prisma Client Additionally to `map`, the `@@id` and `@@unique` attributes take an optional `name` argument that allows you to customize your Prisma Client API. On a model like: ```prisma model User { firstName String lastName String @@id([firstName, lastName]) } ``` the default API for selecting on that primary key uses a generated combination of the fields: ```ts const user = await prisma.user.findUnique({ where: { firstName_lastName: { firstName: 'Paul', lastName: 'Panther', }, }, }) ``` Specifying `@@id([firstName, lastName], name: "fullName")` will change the Prisma Client API to this instead: ```ts highlight=3;edit const user = await prisma.user.findUnique({ where: { //edit-next-line fullName: { firstName: 'Paul', lastName: 'Panther', }, }, }) ``` --- # How to use Prisma ORM with multiple database schemas URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/multi-schema Multiple database schema support is currently available with the PostgreSQL, CockroachDB, and SQL Server connectors. Many database providers allow you to organize database tables into named groups. You can use this to make the logical structure of the data model easier to understand, or to avoid naming collisions between tables. In PostgreSQL, CockroachDB, and SQL Server, these groups are known as schemas. We will refer to them as _database schemas_ to distinguish them from Prisma ORM's own schema. This guide explains how to: - include multiple database schemas in your Prisma schema - apply your schema changes to your database with Prisma Migrate and `db push` - introspect an existing database with multiple database schemas - query across multiple database schemas with Prisma Client ## How to enable the `multiSchema` preview feature Multi-schema support is currently in preview. To enable the `multiSchema` preview feature, add the `multiSchema` feature flag to the `previewFeatures` field of the `generator` block in your Prisma Schema: ```prisma file=schema.prisma highlight=3;add showLineNumbers generator client { provider = "prisma-client-js" //add-next-line previewFeatures = ["multiSchema"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` ## How to include multiple database schemas in your Prisma schema To use multiple database schemas in your Prisma schema file, add the names of your database schemas to an array in the `schemas` field, in the `datasource` block. The following example adds a `"base"` and a `"transactional"` schema: ```prisma file=schema.prisma highlight=9;add showLineNumbers generator client { provider = "prisma-client-js" previewFeatures = ["multiSchema"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") //add-next-line schemas = ["base", "transactional"] } ``` You do not need to change your connection string. The `schema` value of your connection string is the default database schema that Prisma Client connects to and uses for raw queries. All other Prisma Client queries use the schema of the model or enum that you are querying. To designate that a model or enum belongs to a specific database schema, add the `@@schema` attribute with the name of the database schema as a parameter. In the following example, the `User` model is part of the `"base"` schema, and the `Order` model and `Size` enum are part of the `"transactional"` schema: ```prisma file=schema.prisma highlight=5,13;add showLineNumbers model User { id Int @id orders Order[] //add-next-line @@schema("base") } model Order { id Int @id user User @relation(fields: [id], references: [id]) user_id Int //add-next-line @@schema("transactional") } enum Size { Small Medium Large @@schema("transactional") } ``` ### Tables with the same name in different database schemas If you have tables with the same name in different database schemas, you will need to map the table names to unique model names in your Prisma schema. This avoids name conflicts when you query models in Prisma Client. For example, consider a situation where the `config` table in the `base` database schema has the same name as the `config` table in the `users` database schema. To avoid name conflicts, give the models in your Prisma schema unique names (`BaseConfig` and `UserConfig`) and use the `@@map` attribute to map each model to the corresponding table name: ```prisma file=schema.prisma showLineNumbers model BaseConfig { id Int @id @@map("config") @@schema("base") } model UserConfig { id Int @id @@map("config") @@schema("users") } ``` ## How to apply your schema changes with Prisma Migrate and `db push` You can use Prisma Migrate or `db push` to apply changes to a Prisma schema with multiple database schemas. As an example, add a `Profile` model to the `base` schema of the blog post model above: ```prisma file=schema.prisma highlight=4,9-16;add showLineNumbers model User { id Int @id orders Order[] //add-next-line profile Profile? @@schema("base") } //add-start model Profile { id Int @id @default(autoincrement()) bio String user User @relation(fields: [userId], references: [id]) userId Int @unique @@schema("base") } //add-end model Order { id Int @id user User @relation(fields: [id], references: [id]) user_id Int @@schema("transactional") } enum Size { Small Medium Large @@schema("transactional") } ``` You can then apply this schema change to your database. For example, you can use `migrate dev` to create and apply your schema changes as a migration: ```terminal npx prisma migrate dev --name add_profile ``` Note that if you move a model or enum from one schema to another, Prisma ORM deletes the model or enum from the source schema and creates a new one in the target schema. ## How to introspect an existing database with multiple database schemas You can introspect an existing database that has multiple database schemas in the same way that you introspect a database that has a single database schema, using `db pull`: ```terminal npx prisma db pull ``` This updates your Prisma schema to match the current state of the database. If you have tables with the same name in different database schemas, Prisma ORM shows a validation error pointing out the conflict. To fix this, [rename the introspected models with the `@map` attribute](#tables-with-the-same-name-in-different-database-schemas). ## How to query across multiple database schemas with Prisma Client You can query models in multiple database schemas without any change to your Prisma Client query syntax. For example, the following query finds all orders for a given user, using the Prisma schema above: ```ts const orders = await prisma.order.findMany({ where: { user: { id: 1, }, }, }) ``` ## Learn more about the `multiSchema` preview feature To learn more about future plans for the `multiSchema` preview feature, or to give feedback, refer to [our Github issue](https://github.com/prisma/prisma/issues/1122). --- # Unsupported database features URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/unsupported-database-features Not all database functions and features of Prisma ORM's supported databases have a Prisma Schema Language equivalent. Refer to the [database features matrix](/orm/reference/database-features) for a complete list of supported features. ## Native database functions Prisma Schema Language supports several [functions](/orm/reference/prisma-schema-reference#attribute-functions) that you can use to set the default value of a field. The following example uses the Prisma ORM-level `uuid()` function to set the value of the `id` field: ```prisma model Post { id String @id @default(uuid()) } ``` However, you can also use **native database functions** to define default values with [`dbgenerated(...)`](/orm/reference/prisma-schema-reference#dbgenerated) on relational databases (MongoDB does not have the concept of database-level functions). The following example uses the PostgreSQL `gen_random_uuid()` function to populate the `id` field: ```prisma model User { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid } ``` ### When to use a database-level function There are two reasons to use a database-level function: - There is no equivalent Prisma ORM function (for example, `gen_random_bytes` in PostgreSQL). - You cannot or do not want to rely on functions such `uuid()` and `cuid()`, which are only implemented at a Prisma ORM level and do not manifest in the database. Consider the following example, which sets the `id` field to a randomly generated `UUID`: ```prisma model Post { id String @id @default(uuid()) } ``` The UUID is _only_ generated if you use Prisma Client to create the `Post`. If you create posts in any other way, such as a bulk import script written in plain SQL, you must generate the UUID yourself. ### Enable PostgreSQL extensions for native database functions In PostgreSQL, some native database functions are part of an extension. For example, in PostgreSQL versions 12.13 and earlier, the `gen_random_uuid()` function is part of the [`pgcrypto`](https://www.postgresql.org/docs/10/pgcrypto.html) extension. To use a PostgreSQL extension, you must first install it on the file system of your database server. In Prisma ORM versions 4.5.0 and later, you can then activate the extension by declaring it in your Prisma schema with the [`postgresqlExtensions` preview feature](/orm/prisma-schema/postgresql-extensions): ```prisma file=schema.prisma highlight=3,9;add showLineNumbers generator client { provider = "prisma-client-js" //add-next-line previewFeatures = ["postgresqlExtensions"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") //add-next-line extensions = [pgcrypto] } ``` In earlier versions of Prisma ORM, you must instead run a SQL command to activate the extension: ```sql CREATE EXTENSION IF NOT EXISTS pgcrypto; ``` If your project uses [Prisma Migrate](/orm/prisma-migrate), you must [install the extension as part of a migration](/orm/prisma-migrate/workflows/native-database-functions) . Do not install the extension manually, because it is also required by the shadow database. Prisma Migrate returns the following error if the extension is not available: ``` Migration `20210221102106_failed_migration` failed to apply cleanly to a temporary database. Database error: Error querying the database: db error: ERROR: type "pgcrypto" does not exist ``` ## Unsupported field types Some database types of relational databases, such as `polygon` or `geometry`, do not have a Prisma Schema Language equivalent. Use the [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) field type to represent the field in your Prisma schema: ```prisma highlight=3;normal model Star { id Int @id @default(autoincrement()) //highlight-next-line position Unsupported("circle")? @default(dbgenerated("'<(10,4),11>'::circle")) } ``` The `prisma migrate dev` and `prisma db push` command will both create a `position` field of type `circle` in the database. However, the field will not be available in the generated Prisma Client. ## Unsupported database features Some features, like SQL views or partial indexes, cannot be represented in the Prisma schema. If your project uses [Prisma Migrate](/orm/prisma-migrate), you must [include unsupported features as part of a migration](/orm/prisma-migrate/workflows/unsupported-database-features) . --- # Table inheritance URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/table-inheritance ## Overview Table inheritance is a software design pattern that allows the modeling of hierarchical relationships between entities. Using table inheritance on the database level can also enable the use of union types in your JavaScript/TypeScript application or share a set of common properties across multiple models. This page introduces two approaches to table inheritance and explains how to use them with Prisma ORM. A common use case for table inheritance may be when an application needs to display a _feed_ of some kind of _content activities_. A content activity in this case, could be a _video_ or an _article_. As an example, let's assume that: - a content activity always has an `id` and a `url` - in addition to `id` and a `url`, a video also has a `duration` (modeled as an `Int`) - in addition to `id` and a `url`, an article also a `body` (modeled as a `String`) ### Use cases #### Union types Union types are a convenient feature in TypeScript that allows developers to work more flexibly with the types in their data model. In TypeScript, union types look as follows: ```ts no-copy type Activity = Video | Article ``` While [it's currently not possible to model union types in the Prisma schema](https://github.com/prisma/prisma/issues/2505), you can use them with Prisma ORM by using table inheritance and some additional type definitions. #### Sharing properties across multiple models If you have a use case where multiple models should share a particular set of properties, you can model this using table inheritance as well. For example, if both the `Video` and `Article` models from above should have a shared `title` property, you can achieve this with table inheritance as well. ### Example In a simple Prisma schema, this would look as follows. Note that we're adding a `User` model as well to illustrate how this can work with relations: ```prisma file=schema.prisma showLineNumbers model Video { id Int @id url String @unique duration Int user User @relation(fields: [userId], references: [id]) userId Int } model Article { id Int @id url String @unique body String user User @relation(fields: [userId], references: [id]) userId Int } model User { id Int @id name String videos Video[] articles Article[] } ``` Let's investigate how we can model this using table inheritance. ### Single-table vs multi-table inheritance Here is a quick comparison of the two main approaches for table inheritance: - **Single-table inheritance (STI)**: Uses a _single_ table to store data of _all_ the different entities in one location. In our example, there'd be a single `Activity` table with the `id`, `url` as well as the `duration` and `body` column. It also uses a `type` column that indicates whether an _activity_ is a _video_ or an _article_. - **Multi-table inheritance (MTI)**: Uses _multiple_ tables to store the data of the different entities separately and links them via foreign keys. In our example, there'd be an `Activity` table with the `id`, `url` column, a `Video` table with the `duration` and a foreign key to `Activity` as well as an `Article` table with the `body` and a foreign key. There is also a `type` column that acts as a discriminator and indicates whether an _activity_ is a _video_ or an _article_. Note that multi-table inheritance is also sometimes called _delegated types_. You can learn about the tradeoffs of both approaches [below](#tradeoffs-between-sti-and-mti). ## Single-table inheritance (STI) ### Data model Using STI, the above scenario can be modeled as follows: ```prisma model Activity { id Int @id // shared url String @unique // shared duration Int? // video-only body String? // article-only type ActivityType // discriminator owner User @relation(fields: [ownerId], references: [id]) ownerId Int } enum ActivityType { Video Article } model User { id Int @id @default(autoincrement()) name String? activities Activity[] } ``` A few things to note: - The model-specific properties `duration` and `body` must be marked as optional (i.e., with `?`). That's because a record in the `Activity` table that represents a _video_ must not have a value for `body`. Conversely, an `Activity` record representing an _article_ can never have a `duration` set. - The `type` discriminator column indicates whether each record represents a _video_ or an _article_ item. ### Prisma Client API Due to how Prisma ORM generates types and an API for the data model, there will only to be an `Activity` type and the CRUD queries that belong to it (`create`, `update`, `delete`, ...) available to you. #### Querying for videos and articles You can now query for only _videos_ or _articles_ by filtering on the `type` column. For example: ```ts // Query all videos const videos = await prisma.activity.findMany({ where: { type: 'Video' }, }) // Query all articles const articles = await prisma.activity.findMany({ where: { type: 'Article' }, }) ``` #### Defining dedicated types When querying for videos and articles like that, TypeScript will still only recognize an `Activity` type. That can be annoying because even the objects in `videos` will have (optional) `body` and the objects in `articles` will have (optional) `duration` fields. If you want to have type safety for these objects, you need to define dedicated types for them. You can do this, for example, by using the generated `Activity` type and the TypeScript `Omit` utility type to remove properties from it: ```ts import { Activity } from '@prisma/client' type Video = Omit type Article = Omit ``` In addition, it will be helpful to create mapping functions that convert an object of type `Activity` to the `Video` and `Article` types: ```ts function activityToVideo(activity: Activity): Video { return { url: activity.url, duration: activity.duration ? activity.duration : -1, ownerId: activity.ownerId, } as Video } function activityToArticle(activity: Activity): Article { return { url: activity.url, body: activity.body ? activity.body : '', ownerId: activity.ownerId, } as Article } ``` Now you can turn an `Activity` into a more specific type (i.e., `Article` or `Video`) after querying: ```ts const videoActivities = await prisma.activity.findMany({ where: { type: 'Video' }, }) const videos: Video[] = videoActivities.map(activityToVideo) ``` #### Using Prisma Client extension for a more convenient API You can use [Prisma Client extensions](/orm/prisma-client/client-extensions) to create a more convenient API for the table structures in your database. ## Multi-table inheritance (MTI) ### Data model Using MTI, the above scenario can be modeled as follows: ```prisma model Activity { id Int @id @default(autoincrement()) url String // shared type ActivityType // discriminator video Video? // model-specific 1-1 relation article Article? // model-specific 1-1 relation owner User @relation(fields: [ownerId], references: [id]) ownerId Int } model Video { id Int @id @default(autoincrement()) duration Int // video-only activityId Int @unique activity Activity @relation(fields: [activityId], references: [id]) } model Article { id Int @id @default(autoincrement()) body String // article-only activityId Int @unique activity Activity @relation(fields: [activityId], references: [id]) } enum ActivityType { Video Article } model User { id Int @id @default(autoincrement()) name String? activities Activity[] } ``` A few things to note: - A 1-1 relation is needed between `Activity` and `Video` as well as `Activity` and `Article`. This relationship is used to fetch the specific information about a record when needed. - The model-specific properties `duration` and `body` can be made _required_ with this approach. - The `type` discriminator column indicates whether each record represents a _video_ or an _article_ item. ### Prisma Client API This time, you can query for videos and articles directly via the `video` and `article` properties on your `PrismaClient` instance. #### Querying for videos and articles If you want to access the shared properties, you need to use `include` to fetch the relation to `Activity`. ```ts // Query all videos const videos = await prisma.video.findMany({ include: { activity: true }, }) // Query all articles const articles = await prisma.article.findMany({ include: { activity: true }, }) ``` Depending on your needs, you may also query the other way around by filtering on the `type` discriminator column: ```ts // Query all videos const videoActivities = await prisma.activity.findMany({ where: { type: 'Video' } include: { video: true } }) ``` #### Defining dedicated types While a bit more convenient in terms of types compared to STI, the generated typings likely still won't fit all your needs. Here's how you can define `Video` and `Article` types by combining Prisma ORM's generated `Video` and `Article` types with the `Activity` type. These combinations create a new type with the desired properties. Note that we're also omitting the `type` discriminator column because that's not needed anymore on the specific types: ```ts import { Video as VideoDB, Article as ArticleDB, Activity, } from '@prisma/client' type Video = Omit type Article = Omit ``` Once these types are defined, you can define mapping functions to convert the types you receive from the queries above into the desired `Video` and `Article` types. Here's the example for the `Video` type: ```ts import { Prisma, Video as VideoDB, Activity } from '@prisma/client' type Video = Omit // Create `VideoWithActivity` typings for the objects returned above const videoWithActivity = Prisma.validator()({ include: { activity: true }, }) type VideoWithActivity = Prisma.VideoGetPayload // Map to `Video` type function toVideo(a: VideoWithActivity): Video { return { id: a.id, url: a.activity.url, ownerId: a.activity.ownerId, duration: a.duration, activityId: a.activity.id, } } ``` Now you can take the objects returned by the queries above and transform them using `toVideo`: ```ts const videoWithActivities = await prisma.video.findMany({ include: { activity: true }, }) const videos: Video[] = videoWithActivities.map(toVideo) ``` #### Using Prisma Client extension for a more convenient API You can use [Prisma Client extensions](/orm/prisma-client/client-extensions) to create a more convenient API for the table structures in your database. ## Tradeoffs between STI and MTI - **Data model**: The data model may feel more clean with MTI. With STI, you may end up with very wide rows and lots of columns that have `NULL` values in them. - **Performance**: MTI may come with a performance cost because you need to join the parent and child tables to access _all_ properties relevant for a model. - **Typings**: With Prisma ORM, MTI gives you proper typings for the specific models (i.e., `Article` and `Video` in the examples above) already, while you need to create these from scratch with STI. - **IDs / Primary keys**: With MTI, records have two IDs (one on the parent and another on the child table) that may not match. You need to consider this in the business logic of your application. ## Third-party solutions While Prisma ORM doesn't natively support union types or polymorphism at the moment, you can check out [Zenstack](https://github.com/zenstackhq/zenstack) which is adding an extra layer of features to the Prisma schema. Read their [blog post about polymorphism in Prisma ORM](https://zenstack.dev/blog/polymorphism) to learn more. --- # Data model URL: https://www.prisma.io/docs/orm/prisma-schema/data-model/index ## In this section --- # Introspection URL: https://www.prisma.io/docs/orm/prisma-schema/introspection You can introspect your database using the Prisma CLI in order to generate the [data model](/orm/prisma-schema/data-model) in your [Prisma schema](/orm/prisma-schema). The data model is needed to [generate Prisma Client](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names). Introspection is often used to generate an _initial_ version of the data model when [adding Prisma ORM to an existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-postgresql). However, it can also be [used _repeatedly_ in an application](#introspection-with-an-existing-schema). This is most commonly the case when you're _not_ using [Prisma Migrate](/orm/prisma-migrate) but perform schema migrations using plain SQL or another migration tool. In that case, you also need to re-introspect your database and subsequently re-generate Prisma Client to reflect the schema changes in your [Prisma Client API](/orm/prisma-client). ## What does introspection do? Introspection has one main function: Populate your Prisma schema with a data model that reflects the current database schema. ![Introspect your database with Prisma](/img/orm/prisma-db-pull-generate-schema.png) Here's an overview of its main functions on SQL databases: - Map _tables_ in the database to [Prisma models](/orm/prisma-schema/data-model/models#defining-models) - Map _columns_ in the database to the [fields](/orm/prisma-schema/data-model/models#defining-fields) of Prisma models - Map _indexes_ in the database to [indexes](/orm/prisma-schema/data-model/models#defining-an-index) in the Prisma schema - Map _database constraints_ to [attributes](/orm/prisma-schema/data-model/models#defining-attributes) or [type modifiers](/orm/prisma-schema/data-model/models#type-modifiers) in the Prisma schema On MongoDB, the main functions are the following: - Map _collections_ in the database to [Prisma models](/orm/prisma-schema/data-model/models#defining-models). Because a _collection_ in MongoDB doesn't have a predefined structure, Prisma ORM _samples_ the _documents_ in the collection and derives the model structure accordingly (i.e. it maps the fields of the _document_ to the [fields](/orm/prisma-schema/data-model/models#defining-fields) of the Prisma model). If _embedded types_ are detected in a collection, these will be mapped to [composite types](/orm/prisma-schema/data-model/models#defining-composite-types) in the Prisma schema. - Map _indexes_ in the database to [indexes](/orm/prisma-schema/data-model/models#defining-an-index) in the Prisma schema, if the collection contains at least one document contains a field included in the index You can learn more about how Prisma ORM maps types from the database to the types available in the Prisma schema on the respective docs page for the data source connector: - [PostgreSQL](/orm/overview/databases/postgresql#type-mapping-between-postgresql-and-prisma-schema) - [MySQL](/orm/overview/databases/mysql#type-mapping-between-mysql-to-prisma-schema) - [SQLite](/orm/overview/databases/sqlite#type-mapping-between-sqlite-to-prisma-schema) - [Microsoft SQL Server](/orm/overview/databases/sql-server#type-mapping-between-microsoft-sql-server-to-prisma-schema) ## The `prisma db pull` command You can introspect your database using the `prisma db pull` command of the [Prisma CLI](/orm/tools/prisma-cli#installation). Note that using this command requires your [connection URL](/orm/reference/connection-urls) to be set in your Prisma schema [`datasource`](/orm/prisma-schema/overview/data-sources). Here's a high-level overview of the steps that `prisma db pull` performs internally: 1. Read the [connection URL](/orm/reference/connection-urls) from the `datasource` configuration in the Prisma schema 1. Open a connection to the database 1. Introspect database schema (i.e. read tables, columns and other structures ...) 1. Transform database schema into Prisma schema data model 1. Write data model into Prisma schema or [update existing schema](#introspection-with-an-existing-schema) ## Introspection workflow The typical workflow for projects that are not using Prisma Migrate, but instead use plain SQL or another migration tool looks as follows: 1. Change the database schema (e.g. using plain SQL) 1. Run `prisma db pull` to update the Prisma schema 1. Run `prisma generate` to update Prisma Client 1. Use the updated Prisma Client in your application Note that as you evolve the application, [this process can be repeated for an indefinite number of times](#introspection-with-an-existing-schema). ![Introspect workflow](/img/orm/prisma-evolve-app-workflow.png) ## Rules and conventions Prisma ORM employs a number of conventions for translating a database schema into a data model in the Prisma schema: ### Model, field and enum names Field, model and enum names (identifiers) must start with a letter and generally must only contain underscores, letters and digits. You can find the naming rules and conventions for each of these identifiers on the respective docs page: - [Naming models](/orm/reference/prisma-schema-reference#naming-conventions) - [Naming fields](/orm/reference/prisma-schema-reference#naming-conventions-1) - [Naming enums](/orm/reference/prisma-schema-reference#naming-conventions-2) The general rule for identifiers is that they need to adhere to this regular expression: ``` [A-Za-z][A-Za-z0-9_]* ``` #### Sanitization of invalid characters **Invalid characters** are being sanitized during introspection: - If they appear _before_ a letter in an identifier, they get dropped. - If they appear _after_ the first letter, they get replaced by an underscore. Additionally, the transformed name is mapped to the database using `@map` or `@@map` to retain the original name. Consider the following table as an example: ```sql CREATE TABLE "42User" ( _id SERIAL PRIMARY KEY, _name VARCHAR(255), two$two INTEGER ); ``` Because the leading `42` in the table name as well as the leading underscores and the `$` on the columns are forbidden in Prisma ORM, introspection adds the `@map` and `@@map` attributes so that these names adhere to Prisma ORM's naming conventions: ```prisma model User { id Int @id @default(autoincrement()) @map("_id") name String? @map("_name") two_two Int? @map("two$two") @@map("42User") } ``` #### Duplicate Identifiers after Sanitization If sanitization results in duplicate identifiers, no immediate error handling is in place. You get the error later and can manually fix it. Consider the case of the following two tables: ```sql CREATE TABLE "42User" ( _id SERIAL PRIMARY KEY ); CREATE TABLE "24User" ( _id SERIAL PRIMARY KEY ); ``` This would result in the following introspection result: ```prisma model User { id Int @id @default(autoincrement()) @map("_id") @@map("42User") } model User { id Int @id @default(autoincrement()) @map("_id") @@map("24User") } ``` Trying to generate your Prisma Client with `prisma generate` you would get the following error: ``` npx prisma generate ``` ```code no-copy $ npx prisma generate Error: Schema parsing error: The model "User" cannot be defined because a model with that name already exists. --> schema.prisma:17 | 16 | } 17 | model User { | Validation Error Count: 1 ``` In this case, you must manually change the name of one of the two generated `User` models because duplicate model names are not allowed in the Prisma schema. ### Order of fields Introspection lists model fields in the same order as the corresponding table columns in the database. ### Order of attributes Introspection adds attributes in the following order (this order is mirrored by `prisma format`): - Block level: `@@id`, `@@unique`, `@@index`, `@@map` - Field level : `@id`, `@unique`, `@default`, `@updatedAt`, `@map`, `@relation` ### Relations Prisma ORM translates foreign keys that are defined on your database tables into [relations](/orm/prisma-schema/data-model/relations). #### One-to-one relations Prisma ORM adds a [one-to-one](/orm/prisma-schema/data-model/relations/one-to-one-relations) relation to your data model when the foreign key on a table has a `UNIQUE` constraint, e.g.: ```sql CREATE TABLE "User" ( id SERIAL PRIMARY KEY ); CREATE TABLE "Profile" ( id SERIAL PRIMARY KEY, "user" integer NOT NULL UNIQUE, FOREIGN KEY ("user") REFERENCES "User"(id) ); ``` Prisma ORM translates this into the following data model: ```prisma model User { id Int @id @default(autoincrement()) Profile Profile? } model Profile { id Int @id @default(autoincrement()) user Int @unique User User @relation(fields: [user], references: [id]) } ``` #### One-to-many relations By default, Prisma ORM adds a [one-to-many](/orm/prisma-schema/data-model/relations/one-to-many-relations) relation to your data model for a foreign key it finds in your database schema: ```sql CREATE TABLE "User" ( id SERIAL PRIMARY KEY ); CREATE TABLE "Post" ( id SERIAL PRIMARY KEY, "author" integer NOT NULL, FOREIGN KEY ("author") REFERENCES "User"(id) ); ``` These tables are transformed into the following models: ```prisma model User { id Int @id @default(autoincrement()) Post Post[] } model Post { id Int @id @default(autoincrement()) author Int User User @relation(fields: [author], references: [id]) } ``` #### Many-to-many relations [Many-to-many](/orm/prisma-schema/data-model/relations/many-to-many-relations) relations are commonly represented as [relation tables](/orm/prisma-schema/data-model/relations/many-to-many-relations#relation-tables) in relational databases. Prisma ORM supports two ways for defining many-to-many relations in the Prisma schema: - [Implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations) (Prisma ORM manages the relation table under the hood) - [Explicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#explicit-many-to-many-relations) (the relation table is present as a [model](/orm/prisma-schema/data-model/models#defining-models)) _Implicit_ many-to-many relations are recognized if they adhere to Prisma ORM's [conventions for relation tables](/orm/prisma-schema/data-model/relations/many-to-many-relations#conventions-for-relation-tables-in-implicit-m-n-relations). Otherwise the relation table is rendered in the Prisma schema as a model (therefore making it an _explicit_ many-to-many relation). This topic is covered extensively on the docs page about [Relations](/orm/prisma-schema/data-model/relations). #### Disambiguating relations Prisma ORM generally omits the `name` argument on the [`@relation`](/orm/prisma-schema/data-model/relations#the-relation-attribute) attribute if it's not needed. Consider the `User` ↔ `Post` example from the previous section. The `@relation` attribute only has the `references` argument, `name` is omitted because it's not needed in this case: ```prisma model Post { id Int @id @default(autoincrement()) author Int User User @relation(fields: [author], references: [id]) } ``` It would be needed if there were _two_ foreign keys defined on the `Post` table: ```sql CREATE TABLE "User" ( id SERIAL PRIMARY KEY ); CREATE TABLE "Post" ( id SERIAL PRIMARY KEY, "author" integer NOT NULL, "favoritedBy" INTEGER, FOREIGN KEY ("author") REFERENCES "User"(id), FOREIGN KEY ("favoritedBy") REFERENCES "User"(id) ); ``` In this case, Prisma ORM needs to [disambiguate the relation](/orm/prisma-schema/data-model/relations#disambiguating-relations) using a dedicated relation name: ```prisma model Post { id Int @id @default(autoincrement()) author Int favoritedBy Int? User_Post_authorToUser User @relation("Post_authorToUser", fields: [author], references: [id]) User_Post_favoritedByToUser User? @relation("Post_favoritedByToUser", fields: [favoritedBy], references: [id]) } model User { id Int @id @default(autoincrement()) Post_Post_authorToUser Post[] @relation("Post_authorToUser") Post_Post_favoritedByToUser Post[] @relation("Post_favoritedByToUser") } ``` Note that you can rename the [Prisma-ORM level](/orm/prisma-schema/data-model/relations#relation-fields) relation field to anything you like so that it looks friendlier in the generated Prisma Client API. ## Introspection with an existing schema Running `prisma db pull` for relational databases with an existing Prisma Schema merges manual changes made to the schema, with changes made in the database. (This functionality has been added for the first time with version 2.6.0.) For MongoDB, Introspection for now is meant to be done only once for the initial data model. Running it repeatedly will lead to loss of custom changes, as the ones listed below. Introspection for relational databases maintains the following manual changes: - Order of `model` blocks - Order of `enum` blocks - Comments - `@map` and `@@map` attributes - `@updatedAt` - `@default(cuid())` (`cuid()` is a Prisma-ORM level function) - `@default(uuid())` (`uuid()` is a Prisma-ORM level function) - Custom `@relation` names > **Note**: Only relations between models on the database level will be picked up. This means that there **must be a foreign key set**. The following properties of the schema are determined by the database: - Order of fields within `model` blocks - Order of values within `enum` blocks > **Note**: All `enum` blocks are listed below `model` blocks. ### Force overwrite To overwrite manual changes, and generate a schema based solely on the introspected database and ignore any existing Prisma Schema, add the `--force` flag to the `db pull` command: ```terminal npx prisma db pull --force ``` Use cases include: - You want to start from scratch with a schema generated from the underlying database - You have an invalid schema and must use `--force` to make introspection succeed ## Introspecting only a subset of your database schema Introspecting only a subset of your database schema is [not yet officially supported](https://github.com/prisma/prisma/issues/807) by Prisma ORM. However, you can achieve this by creating a new database user that only has access to the tables which you'd like to see represented in your Prisma schema, and then perform the introspection using that user. The introspection will then only include the tables the new user has access to. If your goal is to exclude certain models from the [Prisma Client generation](/orm/prisma-client/setup-and-configuration/generating-prisma-client), you can add the [`@@ignore` attribute](/orm/reference/prisma-schema-reference#ignore-1) to the model definition in your Prisma schema. Ignored models are excluded from the generated Prisma Client. ## Introspection warnings for unsupported features The Prisma Schema Language (PSL) can express a majority of the database features of the [target databases](/orm/reference/supported-databases) Prisma ORM supports. However, there are features and functionality the Prisma Schema Language still needs to express. For these features, the Prisma CLI will surface detect usage of the feature in your database and return a warning. The Prisma CLI will also add a comment in the models and fields the features are in use in the Prisma schema. The warnings will also contain a workaround suggestion. The `prisma db pull` command will surface the following unsupported features: - From version [4.13.0](https://github.com/prisma/prisma/releases/tag/4.13.0): - [Partitioned tables](https://github.com/prisma/prisma/issues/1708) - [PostgreSQL Row Level Security](https://github.com/prisma/prisma/issues/12735) - [Index sort order, `NULLS FIRST` / `NULLS LAST`](https://github.com/prisma/prisma/issues/15466) - [CockroachDB row-level TTL](https://github.com/prisma/prisma/issues/13982) - [Comments](https://github.com/prisma/prisma/issues/8703) - [PostgreSQL deferred constraints](https://github.com/prisma/prisma/issues/8807) - From version [4.14.0](https://github.com/prisma/prisma/releases/tag/4.14.0): - [Check Constraints](https://github.com/prisma/prisma/issues/3388) (MySQL + PostgreSQL) - [Exclusion Constraints](https://github.com/prisma/prisma/issues/17514) - [MongoDB $jsonSchema](https://github.com/prisma/prisma/issues/8135) - From version [4.16.0](https://github.com/prisma/prisma/releases/tag/4.16.0): - [Expression indexes](https://github.com/prisma/prisma/issues/2504) You can find the list of features we intend to support on [GitHub (labeled with `topic:database-functionality`)](https://github.com/prisma/prisma/issues?q=is%3Aopen+label%3A%22topic%3A+database-functionality%22+label%3Ateam%2Fschema+sort%3Aupdated-desc+). ### Workaround for introspection warnings for unsupported features If you are using a relational database and either one of the above features listed in the previous section: 1. Create a draft migration: ```terminal npx prisma migrate dev --create-only ``` 2. Add the SQL that adds the feature surfaced in the warnings. 3. Apply the draft migration to your database: ```terminal npx prisma migrate dev ``` --- # PostgreSQL extensions URL: https://www.prisma.io/docs/orm/prisma-schema/postgresql-extensions This page introduces PostgreSQL extensions and describes how to represent extensions in your Prisma schema, how to introspect existing extensions in your database, and how to apply changes to your extensions to your database with Prisma Migrate. Support for declaring PostgreSQL extensions in your schema is available in preview for the PostgreSQL connector only in Prisma versions 4.5.0 and later. ## What are PostgreSQL extensions? PostgreSQL allows you to extend your database functionality by installing and activating packages known as _extensions_. For example, the `citext` extension adds a case-insensitive string data type. Some extensions, such as `citext`, are supplied directly by PostgreSQL, while other extensions are developed externally. For more information on extensions, see [the PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-createextension.html). To use an extension, it must first be _installed_ on the local file system of your database server. You then need to _activate_ the extension, which runs a script file that adds the new functionality. Note that PostgreSQL's documentation uses the term 'install' to refer to what we call activating an extension. We have used separate terms here to make it clear that these are two different steps. Prisma's `postgresqlExtensions` preview feature allows you to represent PostgreSQL extensions in your Prisma schema. Note that specific extensions may add functionality that is not currently supported by Prisma. For example, an extension may add a type or index that is not supported by Prisma. This functionality must be implemented on a case-by-case basis and is not provided by this preview feature. ## How to enable the `postgresqlExtensions` preview feature Representing PostgreSQL extensions in your Prisma Schema is currently a preview feature. To enable the `postgresqlExtensions` preview feature, you will need to add the `postgresqlExtensions` feature flag to the `previewFeatures` field of the `generator` block in your Prisma schema: ```prisma file=schema.prisma highlight=3;add showLineNumbers generator client { provider = "prisma-client-js" //add-next-line previewFeatures = ["postgresqlExtensions"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` ## How to represent PostgreSQL extensions in your Prisma schema To represent PostgreSQL extensions in your Prisma schema, add the `extensions` field to the `datasource` block of your `schema.prisma` file with an array of the extensions that you require. For example, the following schema lists the `hstore`, `pg_trgm` and `postgis` extensions: ```prisma file=schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") extensions = [hstore(schema: "myHstoreSchema"), pg_trgm, postgis(version: "2.1")] } ``` Each extension name in the Prisma schema can take the following optional arguments: - `schema`: the name of the schema in which to activate the extension's objects. If this argument is not specified, the current default object creation schema is used. - `version`: the version of the extension to activate. If this argument is not specified, the value given in the extension's control file is used. - `map`: the database name of the extension. If this argument is not specified, the name of the extension in the Prisma schema must match the database name. In the example above, the `hstore` extension uses the `myHstoreSchema` schema, and the `postgis` extension is activated with version 2.1 of the extension. The `map` argument is useful when the PostgreSQL extension that you want to activate has a name that is not a valid identifier in the Prisma schema. For example, the `uuid-ossp` PostgreSQL extension name is an invalid identifier because it contains a hyphen. In the following example, the extension is mapped to the valid name `uuidOssp` in the Prisma schema: ```prisma file=schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") extensions = [uuidOssp(map: "uuid-ossp")] } ``` ## How to introspect PostgreSQL extensions To [introspect](/orm/prisma-schema/introspection) PostgreSQL extensions currently activated in your database and add relevant extensions to your Prisma schema, run `npx prisma db pull`. Many PostgreSQL extensions are not relevant to the Prisma schema. For example, some extensions are intended for database administration tasks that do not change the schema. If all these extensions were included, the list of extensions would be very long. To avoid this, Prisma maintains an allowlist of known relevant extensions. The current allowlist is the following: - [`citext`](https://www.postgresql.org/docs/current/citext.html): provides a case-insensitive character string type, `citext` - [`pgcrypto`](https://www.postgresql.org/docs/current/pgcrypto.html): provides cryptographic functions, like `gen_random_uuid()`, to generate universally unique identifiers (UUIDs v4) - [`uuid-ossp`](https://www.postgresql.org/docs/current/uuid-ossp.html): provides functions, like `uuid_generate_v4()`, to generate universally unique identifiers (UUIDs v4) - [`postgis`](https://postgis.net/): adds GIS (Geographic Information Systems) support **Note**: Since PostgreSQL v13, `gen_random_uuid()` can be used without an extension to generate universally unique identifiers (UUIDs v4). Extensions are introspected as follows: - The first time you introspect, all database extensions that are on the allowlist are added to your Prisma schema - When you re-introspect, the behavior depends on whether the extension is on the allowlist or not. - Extensions on the allowlist: - are **added** to your Prisma schema if they are in the database but not in the Prisma schema - are **kept** in your Prisma schema if they are in the Prisma schema and in the database - are **removed** from your Prisma schema if they are in the Prisma schema but not the database - Extensions not on the allowlist: - are **kept** in your Prisma schema if they are in the Prisma schema and in the database - are **removed** from your Prisma schema if they are in the Prisma schema but not the database The `version` argument will not be added to the Prisma schema when you introspect. ## How to migrate PostgreSQL extensions You can update your list of PostgreSQL extensions in your Prisma schema and apply the changes to your database with [Prisma Migrate](/orm/prisma-migrate). This works in a similar way to migration of other elements of your Prisma schema, such as models or fields. However, there are the following differences: - If you remove an extension from your schema but it is still activated on your database, Prisma Migrate will not deactivate it from the database. - If you add a new extension to your schema, it will only be activated if it does not already exist in the database, because the extension may already have been created manually. - If you remove the `version` or `schema` arguments from the extension definition, it has no effect to the extensions in the database in the following migrations. --- # Prisma schema URL: https://www.prisma.io/docs/orm/prisma-schema/index ## In this section --- # Introduction URL: https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/introduction import { Icon } from '@site/src/components/Icon'; Prisma Client is an auto-generated and type-safe query builder that's _tailored_ to your data. The easiest way to get started with Prisma Client is by following the **[Quickstart](/getting-started/quickstart-sqlite)**. Quickstart (5 min) The setup instructions [below](#set-up) provide a high-level overview of the steps needed to set up Prisma Client. If you want to get started using Prisma Client with your own database, follow one of these guides: Set up a new project from scratch

Add Prisma to an existing project
## Set up ### 1. Prerequisites In order to set up Prisma Client, you need a [Prisma schema file](/orm/prisma-schema) with your database connection, the Prisma Client generator, and at least one model: ```prisma file=schema.prisma showLineNumbers datasource db { url = env("DATABASE_URL") provider = "postgresql" } generator client { provider = "prisma-client-js" } model User { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) email String @unique name String? } ``` Also make sure to [install the Prisma CLI](/orm/tools/prisma-cli#installation): ``` npm install prisma --save-dev npx prisma ``` ### 2. Installation Install Prisma Client in your project with the following command: ``` npm install @prisma/client ``` This command also runs the `prisma generate` command, which generates Prisma Client into the [`node_modules/.prisma/client`](/orm/prisma-client/setup-and-configuration/generating-prisma-client#the-prismaclient-npm-package) directory. ### 3. Importing Prisma Client There are multiple ways to import Prisma Client in your project depending on your use case: ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() // use `prisma` in your application to read and write data in your DB ``` ```js const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() // use `prisma` in your application to read and write data in your DB ``` For edge environments, you can import Prisma Client as follows: ```ts import { PrismaClient } from '@prisma/client/edge' const prisma = new PrismaClient() // use `prisma` in your application to read and write data in your DB ``` ```js const { PrismaClient } = require('@prisma/client/edge') const prisma = new PrismaClient() // use `prisma` in your application to read and write data in your DB ``` > **Note**: If you're using [driver adapters](/orm/overview/databases/database-drivers#driver-adapters), you can import from `@prisma/client` directly. No need to import from `@prisma/client/edge`. For Deno, you can import Prisma Client as follows: ```ts file=lib/prisma.ts import { PrismaClient } from './generated/client/deno/edge.ts' const prisma = new PrismaClient() // use `prisma` in your application to read and write data in your DB ``` The import path will depend on the custom `output` specified in Prisma Client's [`generator`](/orm/reference/prisma-schema-reference#fields-1) block in your Prisma schema. ### 4. Use Prisma Client to send queries to your database Once you have instantiated `PrismaClient`, you can start sending queries in your code: ```ts // run inside `async` function const newUser = await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', }, }) const users = await prisma.user.findMany() ``` All Prisma Client methods return an instance of [`PrismaPromise`](/orm/reference/prisma-client-reference#prismapromise-behavior) which only executes when you call `await` or `.then()` or `.catch()`. ### 5. Evolving your application Whenever you make changes to your database that are reflected in the Prisma schema, you need to manually re-generate Prisma Client to update the generated code in the `node_modules/.prisma/client` directory: ``` prisma generate ``` --- # Generating Prisma Client URL: https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/generating-prisma-client Prisma Client is a generated database client that's tailored to your database schema. By default, Prisma Client is generated into the `node_modules/.prisma/client` folder, but we highly recommend [you specify an output location](#using-a-custom-output-path). :::warning In Prisma ORM 7, Prisma Client will no longer be generated in `node_modules` by default and will require an output path to be defined. [Learn more below on how to define an output path](#using-a-custom-output-path). ::: To generate and instantiate Prisma Client: 1. Ensure that you have [Prisma CLI installed on your machine](/orm/tools/prisma-cli#installation). ```terminal npm install prisma --save-dev ``` 1. Add the following `generator` definition to your Prisma schema: ```prisma generator client { provider = "prisma-client-js" output = "app/generated/prisma/client" } ``` :::note Feel free to customize the output location to match your application. Common directories are `app`, `src`, or even the root of your project. ::: 1. Install the `@prisma/client` npm package: ```terminal npm install @prisma/client ``` 1. Generate Prisma Client with the following command: ```terminal prisma generate ``` 1. You can now [instantiate Prisma Client](/orm/prisma-client/setup-and-configuration/instantiate-prisma-client) in your code: ```ts import { PrismaClient } from 'app/generated/prisma/client' const prisma = new PrismaClient() // use `prisma` in your application to read and write data in your DB ``` > **Important**: You need to re-run the `prisma generate` command after every change that's made to your Prisma schema to update the generated Prisma Client code. Here is a graphical illustration of the typical workflow for generation of Prisma Client: ![Graphical illustration of the typical workflow for generation of Prisma Client](./prisma-client-generation-workflow.png) ## The location of Prisma Client :::warning We strongly recommend you define a custom `output` path. In Prisma ORM version `6.6.0`, not defining an `output` path will result in a warning. In Prisma ORM 7, the field will be required. ::: ### Using a custom `output` path You can also specify a custom `output` path on the `generator` configuration, for example (assuming your `schema.prisma` file is located at the default `prisma` subfolder): ```prisma generator client { provider = "prisma-client-js" output = "../src/generated/client" } ``` After running `prisma generate` for that schema file, the Prisma Client package will be located in: ``` ./src/generated/client ``` To import the `PrismaClient` from a custom location (for example, from a file named `./src/script.ts`): ```ts import { PrismaClient } from './generated/client' ``` :::note For improved compatibility with ECMAScript modules (ESM) and to ensure consistent behaviour of Prisma ORM across different Node.js runtimes, you can also use the [`prisma-client` generator](/orm/prisma-schema/overview/generators#prisma-client-early-access) (Preview). This generator is specifically designed to handle common challenges with module resolution and runtime variations, providing a smoother integration experience and less friction with bundlers. ::: ## The `@prisma/client` npm package The `@prisma/client` npm package consists of two key parts: - The `@prisma/client` module itself, which only changes when you re-install the package - The `.prisma/client` folder, which is the [default location](#using-a-custom-output-path) for the unique Prisma Client generated from your schema `@prisma/client/index.d.ts` exports `.prisma/client`: ```ts export * from '.prisma/client' ``` This means that you still import `@prisma/client` in your own `.ts` files: ```ts import { PrismaClient } from '@prisma/client' ``` Prisma Client is generated from your Prisma schema and is unique to your project. Each time you change the schema (for example, by performing a [schema migration](/orm/prisma-migrate)) and run `prisma generate`, Prisma Client's code changes: ![The .prisma and @prisma folders](./prisma-client-node-module.png) The `.prisma` folder is unaffected by [pruning](https://docs.npmjs.com/cli/prune.html) in Node.js package managers. --- # Instantiating Prisma Client URL: https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/instantiate-prisma-client The following example demonstrates how to import and instantiate your [generated client](/orm/prisma-client/setup-and-configuration/generating-prisma-client) from the [default path](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path): ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() ``` ```js const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() ``` :::tip You can further customize `PrismaClient` with [constructor parameters](/orm/reference/prisma-client-reference#prismaclient) — for example, set [logging levels](/orm/prisma-client/observability-and-logging/logging), [transaction options](/orm/prisma-client/queries/transactions#transaction-options) or customize [error formatting](/orm/prisma-client/setup-and-configuration/error-formatting). ::: ## The number of `PrismaClient` instances matters Your application should generally only create **one instance** of `PrismaClient`. How to achieve this depends on whether you are using Prisma ORM in a [long-running application](/orm/prisma-client/setup-and-configuration/databases-connections#prismaclient-in-long-running-applications) or in a [serverless environment](/orm/prisma-client/setup-and-configuration/databases-connections#prismaclient-in-serverless-environments) . The reason for this is that each instance of `PrismaClient` manages a connection pool, which means that a large number of clients can **exhaust the database connection limit**. This applies to all database connectors. If you use the **MongoDB connector**, connections are managed by the MongoDB driver connection pool. If you use a **relational database connector**, connections are managed by Prisma ORM's [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool). Each instance of `PrismaClient` creates its own pool. 1. Each client creates its own instance of the [query engine](/orm/more/under-the-hood/engines). 1. Each query engine creates a [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool) with a default pool size of: - `num_physical_cpus * 2 + 1` for relational databases - [`100` for MongoDB](https://www.mongodb.com/docs/manual/reference/connection-string-options/#mongodb-urioption-urioption.maxPoolSize) 1. Too many connections may start to **slow down your database** and eventually lead to errors such as: ``` Error in connector: Error querying the database: db error: FATAL: sorry, too many clients already at PrismaClientFetcher.request ``` --- # Connection management URL: https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/databases-connections/connection-management `PrismaClient` connects and disconnects from your data source using the following two methods: - [`$connect()`](/orm/reference/prisma-client-reference#connect-1) - [`$disconnect()`](/orm/reference/prisma-client-reference#disconnect-1) In most cases, you **do not need to explicitly call these methods**. `PrismaClient` automatically connects when you run your first query, creates a [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool), and disconnects when the Node.js process ends. See the [connection management guide](/orm/prisma-client/setup-and-configuration/databases-connections) for information about managing connections for different deployment paradigms (long-running processes and serverless functions). ## `$connect()` It is not necessary to call [`$connect()`](/orm/reference/prisma-client-reference#connect-1) thanks to the _lazy connect_ behavior: The `PrismaClient` instance connects lazily when the first request is made to the API (`$connect()` is called for you under the hood). ### Calling `$connect()` explicitly If you need the first request to respond instantly and cannot wait for a lazy connection to be established, you can explicitly call `prisma.$connect()` to establish a connection to the data source: ```ts const prisma = new PrismaClient() // run inside `async` function await prisma.$connect() ``` ## `$disconnect()` When you call [`$disconnect()`](/orm/reference/prisma-client-reference#disconnect-1) , Prisma Client: 1. Runs the [`beforeExit` hook](#exit-hooks) 2. Ends the Query Engine child process and closes all connections In a long-running application such as a GraphQL API, which constantly serves requests, it does not make sense to `$disconnect()` after each request - it takes time to establish a connection, and doing so as part of each request will slow down your application. :::tip To avoid too _many_ connections in a long-running application, we recommend that you [use a single instance of `PrismaClient` across your application](/orm/prisma-client/setup-and-configuration/instantiate-prisma-client#the-number-of-prismaclient-instances-matters). ::: ### Calling `$disconnect()` explicitly One scenario where you should call `$disconnect()` explicitly is where a script: 1. Runs **infrequently** (for example, a scheduled job to send emails each night), which means it does not benefit from a long-running connection to the database _and_ 2. Exists in the context of a **long-running application**, such as a background service. If the application never shuts down, Prisma Client never disconnects. The following script creates a new instance of `PrismaClient`, performs a task, and then disconnects - which closes the connection pool: ```ts highlight=19;normal import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() const emailService = new EmailService() async function main() { const allUsers = await prisma.user.findMany() const emails = allUsers.map((x) => x.email) await emailService.send(emails, 'Hello!') } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` If the above script runs multiple times in the context of a long-running application _without_ calling `$disconnect()`, a new connection pool is created with each new instance of `PrismaClient`. ## Exit hooks From Prisma ORM 5.0.0, the `beforeExit` hook only applies to the [binary Query Engine](/orm/more/under-the-hood/engines#configuring-the-query-engine). The `beforeExit` hook runs when Prisma ORM is triggered externally (e.g. via a `SIGINT` signal) to shut down, and allows you to run code _before_ Prisma Client disconnects - for example, to issue queries as part of a graceful shutdown of a service: ```ts const prisma = new PrismaClient() prisma.$on('beforeExit', async () => { console.log('beforeExit hook') // PrismaClient still available await prisma.message.create({ data: { message: 'Shutting down server', }, }) }) ``` --- # Connection pool URL: https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool The query engine manages a **connection pool** of database connections. The pool is created when Prisma Client opens the _first_ connection to the database, which can happen in one of two ways: - By [explicitly calling `$connect()`](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management#connect) _or_ - By running the first query, which calls `$connect()` under the hood Relational database connectors use Prisma ORM's own connection pool, and the MongoDB connectors uses the [MongoDB driver connection pool](https://github.com/mongodb/specifications/blob/master/source/connection-monitoring-and-pooling/connection-monitoring-and-pooling.rst). ## Relational databases The relational database connectors use Prisma ORM's connection pool. The connection pool has a **connection limit** and a **pool timeout**, which are controlled by connection URL parameters. ### How the connection pool works The following steps describe how the query engine uses the connection pool: 1. The query engine instantiates a connection pool with a [configurable pool size](#setting-the-connection-pool-size) and [pool timeout](#setting-the-connection-pool-timeout). 1. The query engine creates one connection and adds it to the connection pool. 1. When a query comes in, the query engine reserves a connection from the pool to process query. 1. If there are no idle connections available in the connection pool, the query engine opens additional database connections and adds them to the connection pool until the number of database connections reaches the limit defined by `connection_limit`. 1. If the query engine cannot reserve a connection from the pool, queries are added to a FIFO (First In First Out) queue in memory. FIFO means that queries are processed in the order they enter the queue. 1. If the query engine cannot process a query in the queue for **before the [time limit](#default-pool-timeout)**, it throws an exception with error code `P2024` for that query and moves on to the next one in the queue. If you consistently experience pool timeout errors, you need to [optimize the connection pool](/orm/prisma-client/setup-and-configuration/databases-connections#optimizing-the-connection-pool) . ### Connection pool size #### Default connection pool size The default number of connections (pool size) is calculated with the following formula: ```bash num_physical_cpus * 2 + 1 ``` `num_physical_cpus` represents the number of physical CPUs on the machine your application is running on. If your machine has **four** physical CPUs, your connection pool will contain **nine** connections (`4 * 2 + 1 = 9`). Although the formula represents a good starting point, the [recommended connection limit](/orm/prisma-client/setup-and-configuration/databases-connections#recommended-connection-pool-size) also depends on your deployment paradigm - particularly if you are using serverless. #### Setting the connection pool size You can specify the number of connections by explicitly setting the `connection_limit` parameter in your database connection URL. For example, with the following `datasource` configuration in your [Prisma schema](/orm/prisma-schema) the connection pool will have exactly five connections: ```prisma datasource db { provider = "postgresql" url = "postgresql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5" } ``` #### Viewing the connection pool size The number of connections Prisma Client uses can be viewed using [logging](/orm/prisma-client/observability-and-logging/logging) and [metrics](/orm/prisma-client/observability-and-logging/metrics). Using the `info` [logging level](/orm/reference/prisma-client-reference#log-levels), you can log the number of connections in a connection pool that are opened when Prisma Client is instantiated. For example, consider the following Prisma Client instance and invocation: ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient({ log: ['info'], }) async function main() { await prisma.user.findMany() } main() ``` ```text no-copy prisma:info Starting a postgresql pool with 21 connections. ``` When the `PrismaClient` class was instantiated, the logging notified `stdout` that a connection pool with 21 connections was started. Note that the output generated by `log: ['info']` can change in any release without notice. Be aware of this in case you are relying on the output in your application or a tool that you're building. If you need even more insights into the size of your connection pool and the amount of in-use and idle connection, you can use the [metrics](/orm/prisma-client/observability-and-logging/metrics) feature (which is currently in Preview). Consider the following example: ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { await Promise.all([prisma.user.findMany(), prisma.post.findMany()]) const metrics = await prisma.$metrics.json() console.dir(metrics, { depth: Infinity }) } main() ``` ```json no-copy { "counters": [ // ... { "key": "prisma_pool_connections_open", "labels": {}, "value": 2, "description": "Number of currently open Pool Connections" } ], "gauges": [ // ... { "key": "prisma_pool_connections_busy", "labels": {}, "value": 0, "description": "Number of currently busy Pool Connections (executing a datasource query)" }, { "key": "prisma_pool_connections_idle", "labels": {}, "value": 21, "description": "Number of currently unused Pool Connections (waiting for the next datasource query to run)" }, { "key": "prisma_pool_connections_opened_total", "labels": {}, "value": 2, "description": "Total number of Pool Connections opened" } ], "histograms": [ /** ... **/ ] } ``` For more details on what is available in the metrics output, see the [About metrics](/orm/prisma-client/observability-and-logging/metrics#about-metrics) section. ### Connection pool timeout #### Default pool timeout The default connection pool timeout is 10 seconds. If the Query Engine does not get a connection from the database connection pool within that time, it throws an exception and moves on to the next query in the queue. #### Setting the connection pool timeout You can specify the pool timeout by explicitly setting the `pool_timeout` parameter in your database connection URL. In the following example, the pool times out after `2` seconds: ```prisma datasource db { provider = "postgresql" url = "postgresql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5&pool_timeout=2" } ``` #### Disabling the connection pool timeout You disable the connection pool timeout by setting the `pool_timeout` parameter to `0`: ```prisma datasource db { provider = "postgresql" url = "postgresql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5&pool_timeout=0" } ``` You can choose to [disable the connection pool timeout if queries **must** remain in the queue](/orm/prisma-client/setup-and-configuration/databases-connections#disabling-the-pool-timeout) - for example, if you are importing a large number of records in parallel and are confident that the queue will not use up all available RAM before the job is complete. ## MongoDB The MongoDB connector does not use the Prisma ORM connection pool. The connection pool is managed internally by the MongoDB driver and [configured via connection string parameters](https://www.mongodb.com/docs/manual/reference/connection-string-options/#connection-pool-options). ## External connection poolers You cannot increase the `connection_limit` beyond what the underlying database can support. This is a particular challenge in serverless environments, where each function manages an instance of `PrismaClient` - and its own connection pool. Consider introducing [an external connection pooler like PgBouncer](/orm/prisma-client/setup-and-configuration/databases-connections#pgbouncer) to prevent your application or functions from exhausting the database connection limit. ## Manual database connection handling When using Prisma ORM, the database connections are handled on an [engine](https://github.com/prisma/prisma-engines)-level. This means they're not exposed to the developer and it's not possible to manually access them. --- # Configure Prisma Client with PgBouncer URL: https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/databases-connections/pgbouncer An external connection pooler like PgBouncer holds a connection pool to the database, and proxies incoming client connections by sitting between Prisma Client and the database. This reduces the number of processes a database has to handle at any given time. Usually, this works transparently, but some connection poolers only support a limited set of functionality. One common feature that external connection poolers do not support are named prepared statements, which Prisma ORM uses. For these cases, Prisma ORM can be configured to behave differently. :::info Looking for an easy, infrastructure-free solution? Try [Prisma Accelerate](https://www.prisma.io/accelerate?utm_source=docs&utm_campaign=pgbouncer-help)! It requires little to no setup and works seamlessly with all databases supported by Prisma ORM. Ready to begin? Get started with Prisma Accelerate by clicking [here](https://console.prisma.io?utm_source=docs&utm_campaign=pgbouncer-help). ::: ## PgBouncer ### Set PgBouncer to transaction mode For Prisma Client to work reliably, PgBouncer must run in [**Transaction mode**](https://www.pgbouncer.org/features.html). Transaction mode offers a connection for every transaction – a requirement for the Prisma Client to work with PgBouncer. ### Add `pgbouncer=true` for PgBouncer versions below `1.21.0` :::warning We recommend **not** setting `pgbouncer=true` in the database connection string if you're using [PgBouncer `1.21.0`](https://github.com/prisma/prisma/issues/21531#issuecomment-1919059472) or later. ::: To use Prisma Client with PgBouncer, add the `?pgbouncer=true` flag to the PostgreSQL connection URL: ```shell postgresql://USER:PASSWORD@HOST:PORT/DATABASE?pgbouncer=true ``` :::info `PORT` specified for PgBouncer pooling is sometimes different from the default `5432` port. Check your database provider docs for the correct port number. ::: ### Configure `max_prepared_statements` in PgBouncer to be greater than zero Prisma uses prepared statements, and setting [`max_prepared_statements`](https://www.pgbouncer.org/config.html) to a value greater than `0` enables PgBouncer to use those prepared statements. :::info `PORT` specified for PgBouncer pooling is sometimes different from the default `5432` port. Check your database provider docs for the correct port number. ::: ### Prisma Migrate and PgBouncer workaround Prisma Migrate uses **database transactions** to check out the current state of the database and the migrations table. However, the Schema Engine is designed to use a **single connection to the database**, and does not support connection pooling with PgBouncer. If you attempt to run Prisma Migrate commands in any environment that uses PgBouncer for connection pooling, you might see the following error: ```bash Error: undefined: Database error Error querying the database: db error: ERROR: prepared statement "s0" already exists ``` To work around this issue, you must connect directly to the database rather than going through PgBouncer. To achieve this, you can use the [`directUrl`](/orm/reference/prisma-schema-reference#fields) field in your [`datasource`](/orm/reference/prisma-schema-reference#datasource) block. For example, consider the following `datasource` block: ```prisma datasource db { provider = "postgresql" url = "postgres://USER:PASSWORD@HOST:PORT/DATABASE?pgbouncer=true" directUrl = "postgres://USER:PASSWORD@HOST:PORT/DATABASE" } ``` The block above uses a PgBouncer connection string as the primary URL using `url`, allowing Prisma Client to take advantage of the PgBouncer connection pooler. It also provides a connection string directly to the database, without PgBouncer, using the `directUrl` field. This connection string will be used when commands that require a single connection to the database, such as `prisma migrate dev` or `prisma db push`, are invoked. ### PgBouncer with different database providers There are sometimes minor differences in how to connect directly to a Postgres database that depend on the provider hosting the database. Below are links to information on how to set up these connections with providers who have setup steps not covered here in our documentation: - [Connecting directly to a PostgreSQL database hosted on Digital Ocean](https://github.com/prisma/prisma/issues/6157) - [Connecting directly to a PostgreSQL database hosted on ScaleGrid](https://github.com/prisma/prisma/issues/6701#issuecomment-824387959) ## Supabase Supavisor Supabase's Supavisor behaves similarly to [PgBouncer](#pgbouncer). You can add `?pgbouncer=true` to your connection pooled connection string available via your [Supabase database settings](https://supabase.com/dashboard/project/_/settings/database). ## Other external connection poolers Although Prisma ORM does not have explicit support for other connection poolers, if the limitations are similar to the ones of [PgBouncer](#pgbouncer) you can usually also use `pgbouncer=true` in your connection string to put Prisma ORM in a mode that works with them as well. --- # Database connections URL: https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/databases-connections/index Databases can handle a limited number of concurrent connections. Each connection requires RAM, which means that simply increasing the database connection limit without scaling available resources: - ✔ might allow more processes to connect _but_ - ✘ significantly affects **database performance**, and can result in the database being **shut down** due to an out of memory error The way your application **manages connections** also impacts performance. This guide describes how to approach connection management in [serverless environments](#serverless-environments-faas) and [long-running processes](#long-running-processes). This guide focuses on **relational databases** and how to configure and tune the Prisma ORM connection pool (MongoDB uses the MongoDB driver connection pool). ## Long-running processes Examples of long-running processes include Node.js applications hosted on a service like Heroku or a virtual machine. Use the following checklist as a guide to connection management in long-running environments: - Start with the [recommended pool size (`connection_limit`)](#recommended-connection-pool-size) and [tune it](#optimizing-the-connection-pool) - Make sure you have [**one** global instance of `PrismaClient`](#prismaclient-in-long-running-applications) ### Recommended connection pool size The recommended connection pool size (`connection_limit`) to [start with](#optimizing-the-connection-pool) for long-running processes is the **default pool size** (`num_physical_cpus * 2 + 1`) ÷ **number of application instances**. :::info `num_physical_cpus` refers to the the number of CPUs of the machine your application is running on. ::: If you have **one** application instances: - The default pool size applies by default (`num_physical_cpus * 2 + 1`) - you do not need to set the `connection_limit` parameter. - You can optionally [tune the pool size](#optimizing-the-connection-pool). If you have **multiple** application instances: - You must **manually** [set the `connection_limit` parameter](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool#setting-the-connection-pool-size) . For example, if your calculated pool size is _10_ and you have _2_ instances of your app, the `connection_limit` parameter should be **no more than _5_**. - You can optionally [tune the pool size](#optimizing-the-connection-pool). ### `PrismaClient` in long-running applications In **long-running** applications, we recommend that you: - ✔ Create **one** instance of `PrismaClient` and re-use it across your application - ✔ Assign `PrismaClient` to a global variable _in dev environments only_ to [prevent hot reloading from creating new instances](#prevent-hot-reloading-from-creating-new-instances-of-prismaclient) #### Re-using a single `PrismaClient` instance To re-use a single instance, create a module that exports a `PrismaClient` object: ```ts file=client.ts import { PrismaClient } from '@prisma/client' let prisma = new PrismaClient() export default prisma ``` The object is [cached](https://nodejs.org/api/modules.html#modules_caching) the first time the module is imported. Subsequent requests return the cached object rather than creating a new `PrismaClient`: ```ts file=app.ts import prisma from './client' async function main() { const allUsers = await prisma.user.findMany() } main() ``` You do not have to replicate the example above exactly - the goal is to make sure `PrismaClient` is cached. For example, you can [instantiate `PrismaClient` in the `context` object](https://github.com/prisma/prisma-examples/blob/9f1a6b9e7c25b9e1851bd59b273046158d748995/typescript/graphql-express/src/context.ts#L9) that you [pass into an Express app](https://github.com/prisma/prisma-examples/blob/9f1a6b9e7c25b9e1851bd59b273046158d748995/typescript/graphql-express/src/server.ts#L12). #### Do not explicitly `$disconnect()` You [do not need to explicitly `$disconnect()`](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management#calling-disconnect-explicitly) in the context of a long-running application that is continuously serving requests. Opening a new connection takes time and can slow down your application if you disconnect after each query. #### Prevent hot reloading from creating new instances of `PrismaClient` Frameworks like [Next.js](https://nextjs.org/) support hot reloading of changed files, which enables you to see changes to your application without restarting. However, if the framework refreshes the module responsible for exporting `PrismaClient`, this can result in **additional, unwanted instances of `PrismaClient` in a development environment**. As a workaround, you can store `PrismaClient` as a global variable in development environments only, as global variables are not reloaded: ```ts file=client.ts import { PrismaClient } from '@prisma/client' const globalForPrisma = globalThis as unknown as { prisma: PrismaClient } export const prisma = globalForPrisma.prisma || new PrismaClient() if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma ``` The way that you import and use Prisma Client does not change: ```ts file=app.ts import { prisma } from './client' async function main() { const allUsers = await prisma.user.findMany() } main() ``` ## Connections Created per CLI Command In local tests with Postgres, MySQL, and SQLite, each Prisma CLI command typically uses a single connection. The table below shows the ranges observed in these tests. Your environment *may* produce slightly different results. | Command | Connections | Description | |---------|-------------|-------------| | [`migrate status`](/orm/reference/prisma-cli-reference#migrate-status) | 1 | Checks the status of migrations | | [`migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev) | 1–4 | Applies pending migrations in development | | [`migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) | 1–2 | Compares database schema with migration history | | [`migrate reset`](/orm/reference/prisma-cli-reference#migrate-reset) | 1–2 | Resets the database and reapplies migrations | | [`migrate deploy`](/orm/reference/prisma-cli-reference#migrate-deploy) | 1–2 | Applies pending migrations in production | | [`db pull`](/orm/reference/prisma-cli-reference#db-pull) | 1 | Pulls the database schema into the Prisma schema | | [`db push`](/orm/reference/prisma-cli-reference#db-push) | 1–2 | Pushes the Prisma schema to the database | | [`db execute`](/orm/reference/prisma-cli-reference#db-execute) | 1 | Executes raw SQL commands | | [`db seed`](/orm/reference/prisma-cli-reference#db-seed) | 1 | Seeds the database with initial data | ## Serverless environments (FaaS) Examples of serverless environments include Node.js functions hosted on AWS Lambda, Vercel or Netlify Functions. Use the following checklist as a guide to connection management in serverless environments: - Familiarize yourself with the [serverless connection management challenge](#the-serverless-challenge) - [Set pool size (`connection_limit`)](#recommended-connection-pool-size-1) based on whether you have an external connection pooler, and optionally [tune the pool size](#optimizing-the-connection-pool) - [Instantiate `PrismaClient` outside the handler](#instantiate-prismaclient-outside-the-handler) and do not explicitly `$disconnect()` - Configure [function concurrency](#concurrency-limits) and handle [idle connections](#zombie-connections) ### The serverless challenge In a serverless environment, each function creates **its own instance** of `PrismaClient`, and each client instance has its own connection pool. Consider the following example, where a single AWS Lambda function uses `PrismaClient` to connect to a database. The `connection_limit` is **3**: ![An AWS Lambda function connecting to a database.](./serverless-connections.png) A traffic spike causes AWS Lambda to spawn two additional lambdas to handle the increased load. Each lambda creates an instance of `PrismaClient`, each with a `connection_limit` of **3**, which results in a maximum of **9** connections to the database: ![Three AWS Lambda function connecting to a database.](./serverless-connections-2.png) 200 _concurrent functions_ (and therefore 600 possible connections) responding to a traffic spike 📈 can exhaust the database connection limit very quickly. Furthermore, any functions that are **paused** keep their connections open by default and block them from being used by another function. 1. Start by [setting the `connection_limit` to `1`](#recommended-connection-pool-size-1) 2. If a smaller pool size is not enough, consider using an [external connection pooler like PgBouncer](#external-connection-poolers) ### Recommended connection pool size The recommended pool size (`connection_limit`) in serverless environments depends on: - Whether you are using an [external connection pooler](#external-connection-poolers) - Whether your functions are [designed to send queries in parallel](#optimizing-for-parallel-requests) #### Without an external connection pooler If you are **not** using an external connection pooler, _start_ by setting the pool size (`connection_limit`) to **1**, then [optimize](#optimizing-for-parallel-requests). Each incoming request starts a short-lived Node.js process, and many concurrent functions with a high `connection_limit` can quickly **exhaust the _database_ connection limit** during a traffic spike. The following example demonstrates how to set the `connection_limit` to 1 in your connection URL: ``` postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=public&connection_limit=1 ``` ``` mysql://USER:PASSWORD@HOST:PORT/DATABASE?connection_limit=1 ``` :::tip If you are using AWS Lambda and _not_ configuring a `connection_limit`, refer to the following GitHub issue for information about the expected default pool size: https://github.com/prisma/docs/issues/667 ::: #### With an external connection pooler If you are using an external connection pooler, use the default pool size (`num_physical_cpus * 2 + 1`) as a starting point and then [tune the pool size](#optimizing-the-connection-pool). The external connection pooler should prevent a traffic spike from overwhelming the database. #### Optimizing for parallel requests If you rarely or never exceed the database connection limit with the pool size set to 1, you can further optimize the connection pool size. Consider a function that sends queries in parallel: ```ts Promise.all() { query1, query2, query3 query4, ... } ``` If the `connection_limit` is 1, this function is forced to send queries **serially** (one after the other) rather than **in parallel**. This slows down the function's ability to process requests, and may result in pool timeout errors. Tune the `connection_limit` parameter until a traffic spike: - Does not exhaust the database connection limit - Does not result in pool timeout errors ### `PrismaClient` in serverless environments #### Instantiate `PrismaClient` outside the handler Instantiate `PrismaClient` [outside the scope of the function handler](https://github.com/prisma/e2e-tests/blob/5d1041d3f19245d3d237d959eca94d1d796e3a52/platforms/serverless-lambda/index.ts#L3) to increase the chances of reuse. As long as the handler remains 'warm' (in use), the connection is potentially reusable: ```ts highlight=3;normal import { PrismaClient } from '@prisma/client' const client = new PrismaClient() export async function handler() { /* ... */ } ``` #### Do not explicitly `$disconnect()` You [do not need to explicitly `$disconnect()`](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management#calling-disconnect-explicitly) at the end of a function, as there is a possibility that the container might be reused. Opening a new connection takes time and slows down your function's ability to process requests. ### Other serverless considerations #### Container reuse There is no guarantee that subsequent nearby invocations of a function will hit the same container - for example, AWS can choose to create a new container at any time. Code should assume the container to be stateless and create a connection only if it does not exist - Prisma Client JS already implements this logic. #### Zombie connections Containers that are marked "to be removed" and are not being reused still **keep a connection open** and can stay in that state for some time (unknown and not documented from AWS). This can lead to sub-optimal utilization of the database connections. A potential solution is to **clean up idle connections** ([`serverless-mysql`](https://github.com/jeremydaly/serverless-mysql) implements this idea, but cannot be used with Prisma ORM). #### Concurrency limits Depending on your serverless concurrency limit (the number of serverless functions running in parallel), you might still exhaust your database's connection limit. This can happen when too many functions are invoked concurrently, each with its own connection pool, which eventually exhausts the database connection limit. To prevent this, you can [set your serverless concurrency limit](https://docs.aws.amazon.com/lambda/latest/dg/configuration-concurrency.html) to a number lower than the maximum connection limit of your database divided by the number of connections used by each function invocation (as you might want to be able to connect from another client for other purposes). ## Optimizing the connection pool If the query engine cannot [process a query in the queue before the time limit](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool#how-the-connection-pool-works) , you will see connection pool timeout exceptions in your log. A connection pool timeout can occur if: - Many users are accessing your app simultaneously - You send a large number of queries in parallel (for example, using `await Promise.all()`) If you consistently experience connection pool timeouts after configuring the recommended pool size, you can further tune the `connection_limit` and `pool_timeout` parameters. ### Increasing the pool size Increasing the pool size allows the query engine to process a larger number of queries in parallel. Be aware that your database must be able to support the increased number of concurrent connections, otherwise you will **exhaust the database connection limit**. To increase the pool size, manually set the `connection_limit` to a higher number: ```prisma datasource db { provider = "postgresql" url = "postgresql://johndoe:mypassword@localhost:5432/mydb?schema=public&connection_limit=40" } ``` > **Note**: Setting the `connection_limit` to 1 in serverless environments is a recommended starting point, but [this value can also be tuned](#optimizing-for-parallel-requests). ### Increasing the pool timeout Increasing the pool timeout gives the query engine more time to process queries in the queue. You might consider this approach in the following scenario: - You have already increased the `connection_limit`. - You are confident that the queue will not grow beyond a certain size, otherwise **you will eventually run out of RAM**. To increase the pool timeout, set the `pool_timeout` parameter to a value larger than the default (10 seconds): ```prisma datasource db { provider = "postgresql" url = "postgresql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5&pool_timeout=20" } ``` ### Disabling the pool timeout Disabling the pool timeout prevents the query engine from throwing an exception after x seconds of waiting for a connection and allows the queue to build up. You might consider this approach in the following scenario: - You are submitting a large number of queries for a limited time - for example, as part of a job to import or update every customer in your database. - You have already increased the `connection_limit`. - You are confident that the queue will not grow beyond a certain size, otherwise **you will eventually run out of RAM**. To disable the pool timeout, set the `pool_timeout` parameter to `0`: ```prisma datasource db { provider = "postgresql" url = "postgresql://johndoe:mypassword@localhost:5432/mydb?connection_limit=5&pool_timeout=0" } ``` ## External connection poolers Connection poolers like [Prisma Accelerate](/accelerate) and PgBouncer prevent your application from exhausting the database's connection limit. If you would like to use the Prisma CLI in order to perform other actions on your database ,e.g. migrations and introspection, you will need to add an environment variable that provides a direct connection to your database in the `datasource.directUrl` property in your Prisma schema: ```env file=.env highlight=4,5;add showLineNumbers # Connection URL to your database using PgBouncer. DATABASE_URL="postgres://root:password@127.0.0.1:54321/postgres?pgbouncer=true" //add-start # Direct connection URL to the database used for migrations DIRECT_URL="postgres://root:password@127.0.0.1:5432/postgres" //add-end ``` You can then update your `schema.prisma` to use the new direct URL: ```prisma file=schema.prisma highlight=4;add showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") //add-next-line directUrl = env("DIRECT_URL") } ``` More information about the `directUrl` field can be found [here](/orm/reference/prisma-schema-reference#fields). ### Prisma Accelerate [Prisma Accelerate](/accelerate) is a managed external connection pooler built by Prisma that is integrated in the [Prisma Data Platform](/platform) and handles connection pooling for you. ### PgBouncer PostgreSQL only supports a certain amount of concurrent connections, and this limit can be reached quite fast when the service usage goes up – especially in [serverless environments](#serverless-environments-faas). [PgBouncer](https://www.pgbouncer.org/) holds a connection pool to the database and proxies incoming client connections by sitting between Prisma Client and the database. This reduces the number of processes a database has to handle at any given time. PgBouncer passes on a limited number of connections to the database and queues additional connections for delivery when connections becomes available. To use PgBouncer, see [Configure Prisma Client with PgBouncer](/orm/prisma-client/setup-and-configuration/databases-connections/pgbouncer). ### AWS RDS Proxy Due to the way AWS RDS Proxy pins connections, [it does not provide any connection pooling benefits](/orm/prisma-client/deployment/caveats-when-deploying-to-aws-platforms#aws-rds-proxy) when used together with Prisma Client. --- # Custom model and field names URL: https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/custom-model-and-field-names The Prisma Client API is generated based on the models in your [Prisma schema](/orm/prisma-schema). Models are _typically_ 1:1 mappings of your database tables. In some cases, especially when using [introspection](/orm/prisma-schema/introspection), it might be useful to _decouple_ the naming of database tables and columns from the names that are used in your Prisma Client API. This can be done via the [`@map` and `@@map`](/orm/prisma-schema/data-model/models#mapping-model-names-to-tables-or-collections) attributes in your Prisma schema. You can use `@map` and `@@map` to rename MongoDB fields and collections respectively. This page uses a relational database example. ## Example: Relational database Assume you have a PostgreSQL relational database schema looking similar to this: ```sql CREATE TABLE users ( user_id SERIAL PRIMARY KEY NOT NULL, name VARCHAR(256), email VARCHAR(256) UNIQUE NOT NULL ); CREATE TABLE posts ( post_id SERIAL PRIMARY KEY NOT NULL, created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, title VARCHAR(256) NOT NULL, content TEXT, author_id INTEGER REFERENCES users(user_id) ); CREATE TABLE profiles ( profile_id SERIAL PRIMARY KEY NOT NULL, bio TEXT, user_id INTEGER NOT NULL UNIQUE REFERENCES users(user_id) ); CREATE TABLE categories ( category_id SERIAL PRIMARY KEY NOT NULL, name VARCHAR(256) ); CREATE TABLE post_in_categories ( post_id INTEGER NOT NULL REFERENCES posts(post_id), category_id INTEGER NOT NULL REFERENCES categories(category_id) ); CREATE UNIQUE INDEX post_id_category_id_unique ON post_in_categories(post_id int4_ops,category_id int4_ops); ``` When introspecting a database with that schema, you'll get a Prisma schema looking similar to this: ```prisma model categories { category_id Int @id @default(autoincrement()) name String? @db.VarChar(256) post_in_categories post_in_categories[] } model post_in_categories { post_id Int category_id Int categories categories @relation(fields: [category_id], references: [category_id], onDelete: NoAction, onUpdate: NoAction) posts posts @relation(fields: [post_id], references: [post_id], onDelete: NoAction, onUpdate: NoAction) @@unique([post_id, category_id], map: "post_id_category_id_unique") } model posts { post_id Int @id @default(autoincrement()) created_at DateTime? @default(now()) @db.Timestamptz(6) title String @db.VarChar(256) content String? author_id Int? users users? @relation(fields: [author_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction) post_in_categories post_in_categories[] } model profiles { profile_id Int @id @default(autoincrement()) bio String? user_id Int @unique users users @relation(fields: [user_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction) } model users { user_id Int @id @default(autoincrement()) name String? @db.VarChar(256) email String @unique @db.VarChar(256) posts posts[] profiles profiles? } ``` There are a few "issues" with this Prisma schema when the Prisma Client API is generated: **Adhering to Prisma ORM's naming conventions** Prisma ORM has a [naming convention](/orm/reference/prisma-schema-reference#naming-conventions) of **camelCasing** and using the **singular form** for Prisma models. If these naming conventions are not met, the Prisma schema can become harder to interpret and the generated Prisma Client API will feel less natural. Consider the following, generated model: ```prisma model users { user_id Int @id @default(autoincrement()) name String? @db.VarChar(256) email String @unique @db.VarChar(256) posts posts[] profiles profiles? } ``` Although `profiles` refers to a 1:1 relation, its type is currently called `profiles` in plural, suggesting that there might be many `profiles` in this relation. With Prisma ORM conventions, the models and fields were _ideally_ named as follows: ```prisma model User { user_id Int @id @default(autoincrement()) name String? @db.VarChar(256) email String @unique @db.VarChar(256) posts Post[] profile Profile? } ``` Because these fields are "Prisma ORM-level" [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) that do not manifest you can manually rename them in your Prisma schema. **Naming of annotated relation fields** Foreign keys are represented as a combination of a [annotated relation fields](/orm/prisma-schema/data-model/relations#relation-fields) and its corresponding relation scalar field in the Prisma schema. Here's how all the relations from the SQL schema are currently represented: ```prisma model categories { category_id Int @id @default(autoincrement()) name String? @db.VarChar(256) post_in_categories post_in_categories[] // virtual relation field } model post_in_categories { post_id Int // relation scalar field category_id Int // relation scalar field categories categories @relation(fields: [category_id], references: [category_id], onDelete: NoAction, onUpdate: NoAction) // virtual relation field posts posts @relation(fields: [post_id], references: [post_id], onDelete: NoAction, onUpdate: NoAction) @@unique([post_id, category_id], map: "post_id_category_id_unique") } model posts { post_id Int @id @default(autoincrement()) created_at DateTime? @default(now()) @db.Timestamptz(6) title String @db.VarChar(256) content String? author_id Int? users users? @relation(fields: [author_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction) post_in_categories post_in_categories[] } model profiles { profile_id Int @id @default(autoincrement()) bio String? user_id Int @unique users users @relation(fields: [user_id], references: [user_id], onDelete: NoAction, onUpdate: NoAction) } model users { user_id Int @id @default(autoincrement()) name String? @db.VarChar(256) email String @unique @db.VarChar(256) posts posts[] profiles profiles? } ``` ## Using `@map` and `@@map` to rename fields and models in the Prisma Client API You can "rename" fields and models that are used in Prisma Client by mapping them to the "original" names in the database using the `@map` and `@@map` attributes. For the example above, you could e.g. annotate your models as follows. _After_ you introspected your database with `prisma db pull`, you can manually adjust the resulting Prisma schema as follows: ```prisma model Category { id Int @id @default(autoincrement()) @map("category_id") name String? @db.VarChar(256) post_in_categories PostInCategories[] @@map("categories") } model PostInCategories { post_id Int category_id Int categories Category @relation(fields: [category_id], references: [id], onDelete: NoAction, onUpdate: NoAction) posts Post @relation(fields: [post_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@unique([post_id, category_id], map: "post_id_category_id_unique") @@map("post_in_categories") } model Post { id Int @id @default(autoincrement()) @map("post_id") created_at DateTime? @default(now()) @db.Timestamptz(6) title String @db.VarChar(256) content String? author_id Int? users User? @relation(fields: [author_id], references: [id], onDelete: NoAction, onUpdate: NoAction) post_in_categories PostInCategories[] @@map("posts") } model Profile { id Int @id @default(autoincrement()) @map("profile_id") bio String? user_id Int @unique users User @relation(fields: [user_id], references: [id], onDelete: NoAction, onUpdate: NoAction) @@map("profiles") } model User { id Int @id @default(autoincrement()) @map("user_id") name String? @db.VarChar(256) email String @unique @db.VarChar(256) posts Post[] profiles Profile? @@map("users") } ``` With these changes, you're now adhering to Prisma ORM's naming conventions and the generated Prisma Client API feels more "natural": ```ts // Nested writes const profile = await prisma.profile.create({ data: { bio: 'Hello World', users: { create: { name: 'Alice', email: 'alice@prisma.io', }, }, }, }) // Fluent API const userByProfile = await prisma.profile .findUnique({ where: { id: 1 }, }) .users() ``` :::info `prisma db pull` preserves the custom names you defined via `@map` and `@@map` in your Prisma schema on re-introspecting your database. ::: ## Renaming relation fields Prisma ORM-level [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) (sometimes referred to as "virtual relation fields") only exist in the Prisma schema, but do not actually manifest in the underlying database. You can therefore name these fields whatever you want. Consider the following example of an ambiguous relation in a SQL database: ```sql CREATE TABLE "User" ( id SERIAL PRIMARY KEY ); CREATE TABLE "Post" ( id SERIAL PRIMARY KEY, "author" integer NOT NULL, "favoritedBy" INTEGER, FOREIGN KEY ("author") REFERENCES "User"(id), FOREIGN KEY ("favoritedBy") REFERENCES "User"(id) ); ``` Prisma ORM's introspection will output the following Prisma schema: ```prisma model Post { id Int @id @default(autoincrement()) author Int favoritedBy Int? User_Post_authorToUser User @relation("Post_authorToUser", fields: [author], references: [id], onDelete: NoAction, onUpdate: NoAction) User_Post_favoritedByToUser User? @relation("Post_favoritedByToUser", fields: [favoritedBy], references: [id], onDelete: NoAction, onUpdate: NoAction) } model User { id Int @id @default(autoincrement()) Post_Post_authorToUser Post[] @relation("Post_authorToUser") Post_Post_favoritedByToUser Post[] @relation("Post_favoritedByToUser") } ``` Because the names of the virtual relation fields `Post_Post_authorToUser` and `Post_Post_favoritedByToUser` are based on the generated relation names, they don't look very friendly in the Prisma Client API. In that case, you can rename the relation fields. For example: ```prisma highlight=11-12;edit model Post { id Int @id @default(autoincrement()) author Int favoritedBy Int? User_Post_authorToUser User @relation("Post_authorToUser", fields: [author], references: [id], onDelete: NoAction, onUpdate: NoAction) User_Post_favoritedByToUser User? @relation("Post_favoritedByToUser", fields: [favoritedBy], references: [id], onDelete: NoAction, onUpdate: NoAction) } model User { id Int @id @default(autoincrement()) //edit-start writtenPosts Post[] @relation("Post_authorToUser") favoritedPosts Post[] @relation("Post_favoritedByToUser") //edit-end } ``` :::info `prisma db pull` preserves custom relation fields defined in your Prisma schema on re-introspecting your database. ::: --- # Configuring error formatting URL: https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/error-formatting By default, Prisma Client uses [ANSI escape characters](https://en.wikipedia.org/wiki/ANSI_escape_code) to pretty print the error stack and give recommendations on how to fix a problem. While this is very useful when using Prisma Client from the terminal, in contexts like a GraphQL API, you only want the minimal error without any additional formatting. This page explains how error formatting can be configured with Prisma Client. ## Formatting levels There are 3 error formatting levels: 1. **Pretty Error** (default): Includes a full stack trace with colors, syntax highlighting of the code and extended error message with a possible solution for the problem. 2. **Colorless Error**: Same as pretty errors, just without colors. 3. **Minimal Error**: The raw error message. In order to configure these different error formatting levels, there are two options: - Setting the config options via environment variables - Providing the config options to the `PrismaClient` constructor ## Formatting via environment variables - [`NO_COLOR`](/orm/reference/environment-variables-reference#no_color): If this env var is provided, colors are stripped from the error messages. Therefore you end up with a **colorless error**. The `NO_COLOR` environment variable is a standard described [here](https://no-color.org/). - `NODE_ENV=production`: If the env var `NODE_ENV` is set to `production`, only the **minimal error** will be printed. This allows for easier digestion of logs in production environments. ### Formatting via the `PrismaClient` constructor Alternatively, use the `PrismaClient` [`errorFormat`](/orm/reference/prisma-client-reference#errorformat) parameter to set the error format: ```ts const prisma = new PrismaClient({ errorFormat: 'pretty', }) ``` --- # Read replicas URL: https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/read-replicas Read replicas enable you to distribute workloads across database replicas for high-traffic workloads. The [read replicas extension](https://github.com/prisma/extension-read-replicas), `@prisma/extension-read-replicas`, adds support for read-only database replicas to Prisma Client. The read replicas extension supports Prisma ORM versions [5.2.0](https://github.com/prisma/prisma/releases/tag/5.2.0) and higher. If you run into a bug or have feedback, create a GitHub issue [here](https://github.com/prisma/extension-read-replicas/issues/new). ## Setup the read replicas extension Install the extension: ```terminal npm install @prisma/extension-read-replicas ``` Initialize the extension by extending your Prisma Client instance and provide the extension a connection string that points to your read replica in the `url` option of the extension. ```ts import { PrismaClient } from '@prisma/client' import { readReplicas } from '@prisma/extension-read-replicas' const prisma = new PrismaClient().$extends( readReplicas({ url: process.env.DATABASE_URL_REPLICA, }) ) // Query is run against the database replica await prisma.post.findMany() // Query is run against the primary database await prisma.post.create({ data: {/** */}, }) ``` All read operations, e.g. `findMany`, will be executed against the database replica with the above setup. All write operations — e.g. `create`, `update` — and `$transaction` queries, will be executed against your primary database. If you run into a bug or have feedback, create a GitHub issue [here](https://github.com/prisma/extension-read-replicas/issues/new). ## Configure multiple database replicas The `url` property also accepts an array of values, i.e. an array of all your database replicas you would like to configure: ```ts const prisma = new PrismaClient().$extends( readReplicas({ url: [ process.env.DATABASE_URL_REPLICA_1, process.env.DATABASE_URL_REPLICA_2, ], }) ) ``` If you have more than one read replica configured, a database replica will be randomly selected to execute your query. ## Executing read operations against your primary database You can use the `$primary()` method to explicitly execute a read operation against your primary database: ```ts const posts = await prisma.$primary().post.findMany() ``` ## Executing operations against a database replica You can use the `$replica()` method to explicitly execute your query against a replica instead of your primary database: ```ts const result = await prisma.$replica().user.findFirst(...) ``` --- # Database polyfills URL: https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/database-polyfills Prisma Client provides features that are typically either not achievable with particular databases or require extensions. These features are referred to as _polyfills_. For all databases, this includes: - Initializing [ID](/orm/prisma-schema/data-model/models#defining-an-id-field) values with `cuid` and `uuid` values - Using [`@updatedAt`](/orm/prisma-schema/data-model/models#defining-attributes) to store the time when a record was last updated For relational databases, this includes: - [Implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations) For MongoDB, this includes: - [Relations in general](/orm/prisma-schema/data-model/relations) - foreign key relations between documents are not enforced in MongoDB --- # Setup & configuration URL: https://www.prisma.io/docs/orm/prisma-client/setup-and-configuration/index This section describes how to set up, generate, configure, and instantiate `PrismaClient` , as well as when and how to actively [manage connections](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management). ## In this section --- # CRUD URL: https://www.prisma.io/docs/orm/prisma-client/queries/crud This page describes how to perform CRUD operations with your generated Prisma Client API. CRUD is an acronym that stands for: - [Create](#create) - [Read](#read) - [Update](#update) - [Delete](#delete) Refer to the [Prisma Client API reference documentation](/orm/reference/prisma-client-reference) for detailed explanations of each method. ## Example schema All examples are based on the following schema:
Expand for sample schema ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model ExtendedProfile { id Int @id @default(autoincrement()) biography String user User @relation(fields: [userId], references: [id]) userId Int @unique } model User { id Int @id @default(autoincrement()) name String? email String @unique profileViews Int @default(0) role Role @default(USER) coinflips Boolean[] posts Post[] profile ExtendedProfile? } model Post { id Int @id @default(autoincrement()) title String published Boolean @default(true) author User @relation(fields: [authorId], references: [id]) authorId Int comments Json? views Int @default(0) likes Int @default(0) categories Category[] } model Category { id Int @id @default(autoincrement()) name String @unique posts Post[] } enum Role { USER ADMIN } ``` ```prisma datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model ExtendedProfile { id String @id @default(auto()) @map("_id") @db.ObjectId biography String user User @relation(fields: [userId], references: [id]) userId String @unique @db.ObjectId } model User { id String @id @default(auto()) @map("_id") @db.ObjectId name String? email String @unique profileViews Int @default(0) role Role @default(USER) coinflips Boolean[] posts Post[] profile ExtendedProfile? } model Post { id String @id @default(auto()) @map("_id") @db.ObjectId title String published Boolean @default(true) author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId comments Json? views Int @default(0) likes Int @default(0) categories Category[] } model Category { id String @id @default(auto()) @map("_id") @db.ObjectId name String @unique posts Post[] } enum Role { USER ADMIN } ```
For **relational databases**, use `db push` command to push the example schema to your own database ```terminal npx prisma db push ``` For **MongoDB**, ensure your data is in a uniform shape and matches the model defined in the Prisma schema. ## Create ### Create a single record The following query creates ([`create()`](/orm/reference/prisma-client-reference#create)) a single user with two fields: ```ts const user = await prisma.user.create({ data: { email: 'elsa@prisma.io', name: 'Elsa Prisma', }, }) ``` ```js no-copy { id: 22, name: 'Elsa Prisma', email: 'elsa@prisma.io', profileViews: 0, role: 'USER', coinflips: [] } ``` The user's `id` is auto-generated, and your schema determines [which fields are mandatory](/orm/prisma-schema/data-model/models#optional-and-mandatory-fields). #### Create a single record using generated types The following example produces an identical result, but creates a `UserCreateInput` variable named `user` _outside_ the context of the `create()` query. After completing a simple check ("Should posts be included in this `create()` query?"), the `user` variable is passed into the query: ```ts import { PrismaClient, Prisma } from '@prisma/client' const prisma = new PrismaClient() async function main() { let includePosts: boolean = false let user: Prisma.UserCreateInput // Check if posts should be included in the query if (includePosts) { user = { email: 'elsa@prisma.io', name: 'Elsa Prisma', posts: { create: { title: 'Include this post!', }, }, } } else { user = { email: 'elsa@prisma.io', name: 'Elsa Prisma', } } // Pass 'user' object into query const createUser = await prisma.user.create({ data: user }) } main() ``` For more information about working with generated types, see: [Generated types](/orm/prisma-client/type-safety). ### Create multiple records Prisma Client supports bulk inserts as a GA feature in [2.20.0](https://github.com/prisma/prisma/releases/2.20.0) and later. The following [`createMany()`](/orm/reference/prisma-client-reference#createmany) query creates multiple users and skips any duplicates (`email` must be unique): ```ts const createMany = await prisma.user.createMany({ data: [ { name: 'Bob', email: 'bob@prisma.io' }, { name: 'Bobo', email: 'bob@prisma.io' }, // Duplicate unique key! { name: 'Yewande', email: 'yewande@prisma.io' }, { name: 'Angelique', email: 'angelique@prisma.io' }, ], skipDuplicates: true, // Skip 'Bobo' }) ``` ```js no-copy { count: 3 } ``` Note `skipDuplicates` is not supported when using MongoDB, SQLServer, or SQLite. `createMany()` uses a single `INSERT INTO` statement with multiple values, which is generally more efficient than a separate `INSERT` per row: ```sql BEGIN INSERT INTO "public"."User" ("id","name","email","profileViews","role","coinflips","testing","city","country") VALUES (DEFAULT,$1,$2,$3,$4,DEFAULT,DEFAULT,DEFAULT,$5), (DEFAULT,$6,$7,$8,$9,DEFAULT,DEFAULT,DEFAULT,$10), (DEFAULT,$11,$12,$13,$14,DEFAULT,DEFAULT,DEFAULT,$15), (DEFAULT,$16,$17,$18,$19,DEFAULT,DEFAULT,DEFAULT,$20) ON CONFLICT DO NOTHING COMMIT SELECT "public"."User"."country", "public"."User"."city", "public"."User"."email", SUM("public"."User"."profileViews"), COUNT(*) FROM "public"."User" WHERE 1=1 GROUP BY "public"."User"."country", "public"."User"."city", "public"."User"."email" HAVING AVG("public"."User"."profileViews") >= $1 ORDER BY "public"."User"."country" ASC OFFSET $2 ``` > **Note**: Multiple `create()` statements inside a `$transaction` results in multiple `INSERT` statements. The following video demonstrates how to use `createMany()` and [faker.js](https://github.com/faker-js/faker/) to seed a database with sample data:
### Create records and connect or create related records See [Working with relations > Nested writes](/orm/prisma-client/queries/relation-queries#nested-writes) for information about creating a record and one or more related records at the same time. ### Create and return multiple records :::info This feature is available in Prisma ORM version 5.14.0 and later for PostgreSQL, CockroachDB and SQLite. ::: You can use `createManyAndReturn()` in order to create many records and return the resulting objects. ```ts const users = await prisma.user.createManyAndReturn({ data: [ { name: 'Alice', email: 'alice@prisma.io' }, { name: 'Bob', email: 'bob@prisma.io' }, ], }) ``` ```js no-copy [{ id: 22, name: 'Alice', email: 'alice@prisma.io', profileViews: 0, role: 'USER', coinflips: [] }, { id: 23, name: 'Bob', email: 'bob@prisma.io', profileViews: 0, role: 'USER', coinflips: [] }] ``` :::warning `relationLoadStrategy: join` is not available when using `createManyAndReturn()`. ::: ## Read ### Get record by ID or unique identifier The following queries return a single record ([`findUnique()`](/orm/reference/prisma-client-reference#findunique)) by unique identifier or ID: ```ts // By unique identifier const user = await prisma.user.findUnique({ where: { email: 'elsa@prisma.io', }, }) // By ID const user = await prisma.user.findUnique({ where: { id: 99, }, }) ``` If you are using the MongoDB connector and your underlying ID type is `ObjectId`, you can use the string representation of that `ObjectId`: ```ts // By ID const user = await prisma.user.findUnique({ where: { id: '60d5922d00581b8f0062e3a8', }, }) ``` ### Get all records The following [`findMany()`](/orm/reference/prisma-client-reference#findmany) query returns _all_ `User` records: ```ts const users = await prisma.user.findMany() ``` You can also [paginate your results](/orm/prisma-client/queries/pagination). ### Get the first record that matches a specific criteria The following [`findFirst()`](/orm/reference/prisma-client-reference#findfirst) query returns the _most recently created user_ with at least one post that has more than 100 likes: 1. Order users by descending ID (largest first) - the largest ID is the most recent 2. Return the first user in descending order with at least one post that has more than 100 likes ```ts const findUser = await prisma.user.findFirst({ where: { posts: { some: { likes: { gt: 100, }, }, }, }, orderBy: { id: 'desc', }, }) ``` ### Get a filtered list of records Prisma Client supports [filtering](/orm/prisma-client/queries/filtering-and-sorting) on record fields and related record fields. #### Filter by a single field value The following query returns all `User` records with an email that ends in `"prisma.io"`: ```ts const users = await prisma.user.findMany({ where: { email: { endsWith: 'prisma.io', }, }, }) ``` #### Filter by multiple field values The following query uses a combination of [operators](/orm/reference/prisma-client-reference#filter-conditions-and-operators) to return users whose name start with `E` _or_ administrators with at least 1 profile view: ```ts const users = await prisma.user.findMany({ where: { OR: [ { name: { startsWith: 'E', }, }, { AND: { profileViews: { gt: 0, }, role: { equals: 'ADMIN', }, }, }, ], }, }) ``` #### Filter by related record field values The following query returns users with an email that ends with `prisma.io` _and_ have at least _one_ post (`some`) that is not published: ```ts const users = await prisma.user.findMany({ where: { email: { endsWith: 'prisma.io', }, posts: { some: { published: false, }, }, }, }) ``` See [Working with relations](/orm/prisma-client/queries/relation-queries) for more examples of filtering on related field values. ### Select a subset of fields The following `findUnique()` query uses `select` to return the `email` and `name` fields of a specific `User` record: ```ts const user = await prisma.user.findUnique({ where: { email: 'emma@prisma.io', }, select: { email: true, name: true, }, }) ``` ```js no-copy { email: 'emma@prisma.io', name: "Emma" } ``` For more information about including relations, refer to: - [Select fields](/orm/prisma-client/queries/select-fields) - [Relation queries](/orm/prisma-client/queries/relation-queries) #### Select a subset of related record fields The following query uses a nested `select` to return: - The user's `email` - The `likes` field of each post ```ts const user = await prisma.user.findUnique({ where: { email: 'emma@prisma.io', }, select: { email: true, posts: { select: { likes: true, }, }, }, }) ``` ```js no-copy { email: 'emma@prisma.io', posts: [ { likes: 0 }, { likes: 0 } ] } ``` For more information about including relations, see [Select fields and include relations](/orm/prisma-client/queries/select-fields). ### Select distinct field values See [Select `distinct`](/orm/prisma-client/queries/aggregation-grouping-summarizing#select-distinct) for information about selecting distinct field values. ### Include related records The following query returns all `ADMIN` users and includes each user's posts in the result: ```ts const users = await prisma.user.findMany({ where: { role: 'ADMIN', }, include: { posts: true, }, }) ``` ```js no-copy { "id": 38, "name": "Maria", "email": "maria@prisma.io", "profileViews": 20, "role": "ADMIN", "coinflips": [ true, false, false ], "posts": [] }, { "id": 39, "name": "Oni", "email": "oni2@prisma.io", "profileViews": 20, "role": "ADMIN", "coinflips": [ true, false, false ], "posts": [ { "id": 25, "authorId": 39, "title": "My awesome post", "published": true, "comments": null, "views": 0, "likes": 0 } ] } ``` For more information about including relations, see [Select fields and include relations](/orm/prisma-client/queries/select-fields). #### Include a filtered list of relations See [Working with relations](/orm/prisma-client/queries/relation-queries#filter-a-list-of-relations) to find out how to combine [`include`](/orm/reference/prisma-client-reference#include) and `where` for a filtered list of relations - for example, only include a user's published posts. ## Update ### Update a single record The following query uses [`update()`](/orm/reference/prisma-client-reference#update) to find and update a single `User` record by `email`: ```ts const updateUser = await prisma.user.update({ where: { email: 'viola@prisma.io', }, data: { name: 'Viola the Magnificent', }, }) ``` ```js no-copy { "id": 43, "name": "Viola the Magnificent", "email": "viola@prisma.io", "profileViews": 0, "role": "USER", "coinflips": [], } ``` ### Update multiple records The following query uses [`updateMany()`](/orm/reference/prisma-client-reference#updatemany) to update all `User` records that contain `prisma.io`: ```ts const updateUsers = await prisma.user.updateMany({ where: { email: { contains: 'prisma.io', }, }, data: { role: 'ADMIN', }, }) ``` ```js no-copy { "count": 19 } ``` ### Update and return multiple records :::info This feature is available in Prisma ORM version 6.2.0 and later for PostgreSQL, CockroachDB, and SQLite. ::: You can use `updateManyAndReturn()` in order to update many records and return the resulting objects. ```ts const users = await prisma.user.updateManyAndReturn({ where: { email: { contains: 'prisma.io', } }, data: { role: 'ADMIN' } }) ``` ```js no-copy [{ id: 22, name: 'Alice', email: 'alice@prisma.io', profileViews: 0, role: 'ADMIN', coinflips: [] }, { id: 23, name: 'Bob', email: 'bob@prisma.io', profileViews: 0, role: 'ADMIN', coinflips: [] }] ``` :::warning `relationLoadStrategy: join` is not available when using `updateManyAndReturn()`. ::: ### Update _or_ create records The following query uses [`upsert()`](/orm/reference/prisma-client-reference#upsert) to update a `User` record with a specific email address, or create that `User` record if it does not exist: ```ts const upsertUser = await prisma.user.upsert({ where: { email: 'viola@prisma.io', }, update: { name: 'Viola the Magnificent', }, create: { email: 'viola@prisma.io', name: 'Viola the Magnificent', }, }) ``` ```js no-copy { "id": 43, "name": "Viola the Magnificent", "email": "viola@prisma.io", "profileViews": 0, "role": "ADMIN", "coinflips": [], } ``` From version 4.6.0, Prisma Client carries out upserts with database native SQL commands where possible. [Learn more](/orm/reference/prisma-client-reference#database-upserts). Prisma Client does not have a `findOrCreate()` query. You can use `upsert()` as a workaround. To make `upsert()` behave like a `findOrCreate()` method, provide an empty `update` parameter to `upsert()`. A limitation to using `upsert()` as a workaround for `findOrCreate()` is that `upsert()` will only accept unique model fields in the `where` condition. So it's not possible to use `upsert()` to emulate `findOrCreate()` if the `where` condition contains non-unique fields. ### Update a number field Use [atomic number operations](/orm/reference/prisma-client-reference#atomic-number-operations) to update a number field **based on its current value** - for example, increment or multiply. The following query increments the `views` and `likes` fields by `1`: ```ts const updatePosts = await prisma.post.updateMany({ data: { views: { increment: 1, }, likes: { increment: 1, }, }, }) ``` ### Connect and disconnect related records Refer to [Working with relations](/orm/prisma-client/queries/relation-queries) for information about disconnecting ([`disconnect`](/orm/reference/prisma-client-reference#disconnect)) and connecting ([`connect`](/orm/reference/prisma-client-reference#connect)) related records. ## Delete ### Delete a single record The following query uses [`delete()`](/orm/reference/prisma-client-reference#delete) to delete a single `User` record: ```ts const deleteUser = await prisma.user.delete({ where: { email: 'bert@prisma.io', }, }) ``` Attempting to delete a user with one or more posts result in an error, as every `Post` requires an author - see [cascading deletes](#cascading-deletes-deleting-related-records). ### Delete multiple records The following query uses [`deleteMany()`](/orm/reference/prisma-client-reference#deletemany) to delete all `User` records where `email` contains `prisma.io`: ```ts const deleteUsers = await prisma.user.deleteMany({ where: { email: { contains: 'prisma.io', }, }, }) ``` Attempting to delete a user with one or more posts result in an error, as every `Post` requires an author - see [cascading deletes](#cascading-deletes-deleting-related-records). ### Delete all records The following query uses [`deleteMany()`](/orm/reference/prisma-client-reference#deletemany) to delete all `User` records: ```ts const deleteUsers = await prisma.user.deleteMany({}) ``` Be aware that this query will fail if the user has any related records (such as posts). In this case, you need to [delete the related records first](#cascading-deletes-deleting-related-records). ### Cascading deletes (deleting related records) In [2.26.0](https://github.com/prisma/prisma/releases/tag/2.26.0) and later it is possible to do cascading deletes using the **preview feature** [referential actions](/orm/prisma-schema/data-model/relations/referential-actions). The following query uses [`delete()`](/orm/reference/prisma-client-reference#delete) to delete a single `User` record: ```ts const deleteUser = await prisma.user.delete({ where: { email: 'bert@prisma.io', }, }) ``` However, the example schema includes a **required relation** between `Post` and `User`, which means that you cannot delete a user with posts: ``` The change you are trying to make would violate the required relation 'PostToUser' between the `Post` and `User` models. ``` To resolve this error, you can: - Make the relation optional: ```prisma highlight=3,4;add|5,6;delete model Post { id Int @id @default(autoincrement()) //add-start author User? @relation(fields: [authorId], references: [id]) authorId Int? //add-end //delete-start author User @relation(fields: [authorId], references: [id]) authorId Int //delete-end } ``` - Change the author of the posts to another user before deleting the user. - Delete a user and all their posts with two separate queries in a transaction (all queries must succeed): ```ts const deletePosts = prisma.post.deleteMany({ where: { authorId: 7, }, }) const deleteUser = prisma.user.delete({ where: { id: 7, }, }) const transaction = await prisma.$transaction([deletePosts, deleteUser]) ``` ### Delete all records from all tables Sometimes you want to remove all data from all tables but keep the actual tables. This can be particularly useful in a development environment and whilst testing. The following shows how to delete all records from all tables with Prisma Client and with Prisma Migrate. #### Deleting all data with `deleteMany()` When you know the order in which your tables should be deleted, you can use the [`deleteMany`](/orm/reference/prisma-client-reference#deletemany) function. This is executed synchronously in a [`$transaction`](/orm/prisma-client/queries/transactions) and can be used with all types of databases. ```ts const deletePosts = prisma.post.deleteMany() const deleteProfile = prisma.profile.deleteMany() const deleteUsers = prisma.user.deleteMany() // The transaction runs synchronously so deleteUsers must run last. await prisma.$transaction([deleteProfile, deletePosts, deleteUsers]) ``` ✅ **Pros**: - Works well when you know the structure of your schema ahead of time - Synchronously deletes each tables data ❌ **Cons**: - When working with relational databases, this function doesn't scale as well as having a more generic solution which looks up and `TRUNCATE`s your tables regardless of their relational constraints. Note that this scaling issue does not apply when using the MongoDB connector. > **Note**: The `$transaction` performs a cascading delete on each models table so they have to be called in order. #### Deleting all data with raw SQL / `TRUNCATE` If you are comfortable working with raw SQL, you can perform a `TRUNCATE` query on a table using [`$executeRawUnsafe`](/orm/prisma-client/using-raw-sql/raw-queries#executerawunsafe). In the following examples, the first tab shows how to perform a `TRUNCATE` on a Postgres database by using a `$queryRaw` look up that maps over the table and `TRUNCATES` all tables in a single query. The second tab shows performing the same function but with a MySQL database. In this instance the constraints must be removed before the `TRUNCATE` can be executed, before being reinstated once finished. The whole process is run as a `$transaction` ```ts const tablenames = await prisma.$queryRaw< Array<{ tablename: string }> >`SELECT tablename FROM pg_tables WHERE schemaname='public'` const tables = tablenames .map(({ tablename }) => tablename) .filter((name) => name !== '_prisma_migrations') .map((name) => `"public"."${name}"`) .join(', ') try { await prisma.$executeRawUnsafe(`TRUNCATE TABLE ${tables} CASCADE;`) } catch (error) { console.log({ error }) } ``` ```ts const transactions: PrismaPromise[] = [] transactions.push(prisma.$executeRaw`SET FOREIGN_KEY_CHECKS = 0;`) const tablenames = await prisma.$queryRaw< Array<{ TABLE_NAME: string }> >`SELECT TABLE_NAME from information_schema.TABLES WHERE TABLE_SCHEMA = 'tests';` for (const { TABLE_NAME } of tablenames) { if (TABLE_NAME !== '_prisma_migrations') { try { transactions.push(prisma.$executeRawUnsafe(`TRUNCATE ${TABLE_NAME};`)) } catch (error) { console.log({ error }) } } } transactions.push(prisma.$executeRaw`SET FOREIGN_KEY_CHECKS = 1;`) try { await prisma.$transaction(transactions) } catch (error) { console.log({ error }) } ``` ✅ **Pros**: - Scalable - Very fast ❌ **Cons**: - Can't undo the operation - Using reserved SQL key words as tables names can cause issues when trying to run a raw query #### Deleting all records with Prisma Migrate If you use Prisma Migrate, you can use `migrate reset`, this will: 1. Drop the database 2. Create a new database 3. Apply migrations 4. Seed the database with data ## Advanced query examples ### Create a deeply nested tree of records - A single `User` - Two new, related `Post` records - Connect or create `Category` per post ```ts const u = await prisma.user.create({ include: { posts: { include: { categories: true, }, }, }, data: { email: 'emma@prisma.io', posts: { create: [ { title: 'My first post', categories: { connectOrCreate: [ { create: { name: 'Introductions' }, where: { name: 'Introductions', }, }, { create: { name: 'Social' }, where: { name: 'Social', }, }, ], }, }, { title: 'How to make cookies', categories: { connectOrCreate: [ { create: { name: 'Social' }, where: { name: 'Social', }, }, { create: { name: 'Cooking' }, where: { name: 'Cooking', }, }, ], }, }, ], }, }, }) ``` --- # Select fields URL: https://www.prisma.io/docs/orm/prisma-client/queries/select-fields ## Overview By default, when a query returns records (as opposed to a count), the result includes: - **All scalar fields** of a model (including enums) - **No relations** defined on a model As an example, consider this schema: ```prisma model User { id Int @id @default(autoincrement()) email String @unique name String? role Role @default(USER) posts Post[] } model Post { id Int @id @default(autoincrement()) published Boolean @default(false) title String author User? @relation(fields: [authorId], references: [id]) authorId Int? } enum Role { USER ADMIN } ``` A query to the `User` model will include the `id`, `email`, `name` and `role` fields (because these are _scalar_ fields), but not the `posts` field (because that's a _relation_ field): ```ts const users = await prisma.user.findFirst() ``` ```js no-copy { id: 42, name: "Sabelle", email: "sabelle@prisma.io", role: "ADMIN" } ``` If you want to customize the result and have a different combination of fields returned, you can: - Use [`select`](/orm/reference/prisma-client-reference#select) to return specific fields. You can also use a [nested `select`](/orm/prisma-client/queries/relation-queries#select-specific-fields-of-included-relations) by selecting relation fields. - Use [`omit`](/orm/reference/prisma-client-reference#omit) to exclude specific fields from the result. `omit` can be seen as the "opposite" to `select`. - Use [`include`](/orm/reference/prisma-client-reference#include) to additionally [include relations](/orm/prisma-client/queries/relation-queries#nested-reads). In all cases, the query result will be statically typed, ensuring that you don't accidentally access any fields that you did not actually query from the database. Selecting only the fields and relations that you require rather than relying on the default selection set can reduce the size of the response and improve query speed. Since version [5.9.0](https://github.com/prisma/prisma/releases/tag/5.9.0), when doing a relation query with `include` or by using `select` on a relation field, you can also specify the `relationLoadStrategy` to decide whether you want to use a database-level join or perform multiple queries and merge the data on the application level. This feature is currently in [Preview](/orm/more/releases#preview), you can learn more about it [here](/orm/prisma-client/queries/relation-queries#relation-load-strategies-preview). ## Example schema All following examples on this page are based on the following schema: ```prisma model User { id Int @id name String? email String @unique password String role Role @default(USER) coinflips Boolean[] posts Post[] profile Profile? } model Post { id Int @id title String published Boolean @default(true) author User @relation(fields: [authorId], references: [id]) authorId Int } model Profile { id Int @id biography String user User @relation(fields: [userId], references: [id]) userId Int @unique } enum Role { USER ADMIN } ``` ## Return the default fields The following query returns the default fields (all scalar fields, no relations): ```ts const user = await prisma.user.findFirst() ``` ```js no-copy { id: 22, name: "Alice", email: "alice@prisma.io", password: "mySecretPassword42" role: "ADMIN", coinflips: [true, false], } ``` ## Select specific fields Use `select` to return a _subset_ of fields instead of _all_ fields. The following example returns the `email` and `name` fields only: ```ts const user = await prisma.user.findFirst({ select: { email: true, name: true, }, }) ``` ```js no-copy { name: "Alice", email: "alice@prisma.io", } ``` ## Return nested objects by selecting relation fields You can also return relations by nesting `select` multiple times on [relation fields](/orm/prisma-schema/data-model/relations#relation-fields). The following query uses a nested `select` to select each user's `name` and the `title` of each related post: ```ts highlight=normal;2,5 const usersWithPostTitles = await prisma.user.findFirst({ select: { name: true, posts: { select: { title: true }, }, }, }) ``` ```js no-copy { "name":"Sabelle", "posts":[ { "title":"Getting started with Azure Functions" }, { "title":"All about databases" } ] } ``` The following query uses `select` within an `include`, and returns _all_ user fields and each post's `title` field: ```ts highlight=normal;2,5 const usersWithPostTitles = await prisma.user.findFirst({ include: { posts: { select: { title: true }, }, }, }) ``` ```js no-copy { id: 9 name: "Sabelle", email: "sabelle@prisma.io", password: "mySecretPassword42", role: "USER", coinflips: [], posts:[ { title:"Getting started with Azure Functions" }, { title:"All about databases" } ] } ``` You can nest your queries arbitrarily deep. The following query fetches: - the `title` of a `Post` - the `name` of the related `User` - the `biography` of the related `Profile` ```ts highlight=normal;2,5 const postsWithAuthorsAndProfiles = await prisma.post.findFirst({ select: { title: true, author: { select: { name: true, profile: { select: { biography: true } } }, }, }, }) ``` ```js no-copy { id: 9 title:"All about databases", author: { name: "Sabelle",. profile: { biography: "I like turtles" } } } ``` :::note Be careful when deeply nesting relations because the underlying database query may become slow due it needing to access a lot of different tables. To ensure your queries always have optimal speed, consider adding a caching layer with [Prisma Accelerate](/accelerate) or use [Prisma Optimize](/optimize/) to get query insights and recommendations for performance optimizations. ::: For more information about querying relations, refer to the following documentation: - [Include a relation (including all fields)](/orm/prisma-client/queries/relation-queries#include-all-fields-for-a-specific-relation) - [Select specific relation fields](/orm/prisma-client/queries/relation-queries#select-specific-fields-of-included-relations) ## Omit specific fields There may be situations when you want to return _most_ fields of a model, excluding only a _small_ subset. A common example for this is when you query a `User` but want to exclude the `password` field for security reasons. In these cases, you can use `omit`, which can be seen as the counterpart to `select`: ```ts const users = await prisma.user.findFirst({ omit: { password: true } }) ``` ```js no-copy { id: 9 name: "Sabelle", email: "sabelle@prisma.io", profileViews: 90, role: "USER", coinflips: [], } ``` Notice how the returned object does _not_ contain the `password` field. ## Relation count In [3.0.1](https://github.com/prisma/prisma/releases/3.0.1) and later, you can `include` or `select` a [count of relations](/orm/prisma-client/queries/aggregation-grouping-summarizing#count-relations) alongside fields. For example, a user's post count. --- # Relation queries URL: https://www.prisma.io/docs/orm/prisma-client/queries/relation-queries A key feature of Prisma Client is the ability to query [relations](/orm/prisma-schema/data-model/relations) between two or more models. Relation queries include: - [Nested reads](#nested-reads) (sometimes referred to as _eager loading_) via [`select`](/orm/reference/prisma-client-reference#select) and [`include`](/orm/reference/prisma-client-reference#include) - [Nested writes](#nested-writes) with [transactional](/orm/prisma-client/queries/transactions) guarantees - [Filtering on related records](#relation-filters) Prisma Client also has a [fluent API for traversing relations](#fluent-api). ## Nested reads Nested reads allow you to read related data from multiple tables in your database - such as a user and that user's posts. You can: - Use [`include`](/orm/reference/prisma-client-reference#include) to include related records, such as a user's posts or profile, in the query response. - Use a nested [`select`](/orm/reference/prisma-client-reference#select) to include specific fields from a related record. You can also nest `select` inside an `include`. ### Relation load strategies (Preview) Since version [5.8.0](https://github.com/prisma/prisma/releases/tag/5.8.0), you can decide on a per-query-level _how_ you want Prisma Client to execute a relation query (i.e. what _load strategy_ should be applied) via the `relationLoadStrategy` option for PostgreSQL databases. Since version [5.10.0](https://github.com/prisma/prisma/releases/tag/5.10.0), this feature is also available for MySQL. Because the `relationLoadStrategy` option is currently in Preview, you need to enable it via the `relationJoins` preview feature flag in your Prisma schema file: ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" previewFeatures = ["relationJoins"] } ``` After adding this flag, you need to run `prisma generate` again to re-generate Prisma Client. The `relationJoins` feature is currently available on PostgreSQL, CockroachDB and MySQL. Prisma Client supports two load strategies for relations: - `join` (default): Uses a database-level `LATERAL JOIN` (PostgreSQL) or correlated subqueries (MySQL) and fetches all data with a single query to the database. - `query`: Sends multiple queries to the database (one per table) and joins them on the application level. Another important difference between these two options is that the `join` strategy uses JSON aggregation on the database level. That means that it creates the JSON structures returned by Prisma Client already in the database which saves computation resources on the application level. > **Note**: Once `relationLoadStrategy` moves from [Preview](/orm/more/releases#preview) into [General Availability](/orm/more/releases/#generally-available-ga), `join` will universally become the default for all relation queries. #### Examples You can use the `relationLoadStrategy` option on the top-level in any query that supports `include` or `select`. Here is an example with `include`: ```ts const users = await prisma.user.findMany({ relationLoadStrategy: 'join', // or 'query' include: { posts: true, }, }) ``` And here is another example with `select`: ```ts const users = await prisma.user.findMany({ relationLoadStrategy: 'join', // or 'query' select: { posts: true, }, }) ``` #### When to use which load strategy? - The `join` strategy (default) will be more effective in most scenarios. On PostgreSQL, it uses a combination of `LATERAL JOINs` and JSON aggregation to reduce redundancy in result sets and delegate the work of transforming the query results into the expected JSON structures on the database server. On MySQL, it uses correlated subqueries to fetch the results with a single query. - There may be edge cases where `query` could be more performant depending on the characteristics of the dataset and query. We recommend that you profile your database queries to identify these situations. - Use `query` if you want to save resources on the database server and do heavy-lifting of merging and transforming data in the application server which might be easier to scale. ### Include a relation The following example returns a single user and that user's posts: ```ts const user = await prisma.user.findFirst({ include: { posts: true, }, }) ``` ```js no-copy { id: 19, name: null, email: 'emma@prisma.io', profileViews: 0, role: 'USER', coinflips: [], posts: [ { id: 20, title: 'My first post', published: true, authorId: 19, comments: null, views: 0, likes: 0 }, { id: 21, title: 'How to make cookies', published: true, authorId: 19, comments: null, views: 0, likes: 0 } ] } ``` ### Include all fields for a specific relation The following example returns a post and its author: ```ts const post = await prisma.post.findFirst({ include: { author: true, }, }) ``` ```js no-copy { id: 17, title: 'How to make cookies', published: true, authorId: 16, comments: null, views: 0, likes: 0, author: { id: 16, name: null, email: 'orla@prisma.io', profileViews: 0, role: 'USER', coinflips: [], }, } ``` ### Include deeply nested relations You can nest `include` options to include relations of relations. The following example returns a user's posts, and each post's categories: ```ts const user = await prisma.user.findFirst({ include: { posts: { include: { categories: true, }, }, }, }) ``` ```js no-copy { "id": 40, "name": "Yvette", "email": "yvette@prisma.io", "profileViews": 0, "role": "USER", "coinflips": [], "testing": [], "city": null, "country": "Sweden", "posts": [ { "id": 66, "title": "How to make an omelette", "published": true, "authorId": 40, "comments": null, "views": 0, "likes": 0, "categories": [ { "id": 3, "name": "Easy cooking" } ] }, { "id": 67, "title": "How to eat an omelette", "published": true, "authorId": 40, "comments": null, "views": 0, "likes": 0, "categories": [] } ] } ``` ### Select specific fields of included relations You can use a nested `select` to choose a subset of fields of relations to return. For example, the following query returns the user's `name` and the `title` of each related post: ```ts const user = await prisma.user.findFirst({ select: { name: true, posts: { select: { title: true, }, }, }, }) ``` ```js no-copy { name: "Elsa", posts: [ { title: 'My first post' }, { title: 'How to make cookies' } ] } ``` You can also nest a `select` inside an `include` - the following example returns _all_ `User` fields and the `title` field of each post: ```ts const user = await prisma.user.findFirst({ include: { posts: { select: { title: true, }, }, }, }) ``` ```js no-copy { "id": 1, "name": null, "email": "martina@prisma.io", "profileViews": 0, "role": "USER", "coinflips": [], "posts": [ { "title": "How to grow salad" }, { "title": "How to ride a horse" } ] } ``` Note that you **cannot** use `select` and `include` _on the same level_. This means that if you choose to `include` a user's post and `select` each post's title, you cannot `select` only the users' `email`: ```ts highlight=3,6;delete // The following query returns an exception const user = await prisma.user.findFirst({ //delete-next-line select: { // This won't work! email: true } //delete-next-line include: { // This won't work! posts: { select: { title: true } } }, }) ``` ```code no-copy Invalid `prisma.user.findUnique()` invocation: { where: { id: 19 }, select: { ~~~~~~ email: true }, include: { ~~~~~~~ posts: { select: { title: true } } } } Please either use `include` or `select`, but not both at the same time. ``` Instead, use nested `select` options: ```ts const user = await prisma.user.findFirst({ select: { // This will work! email: true, posts: { select: { title: true, }, }, }, }) ``` ## Relation count In [3.0.1](https://github.com/prisma/prisma/releases/3.0.1) and later, you can [`include` or `select` a count of relations](/orm/prisma-client/queries/aggregation-grouping-summarizing#count-relations) alongside fields - for example, a user's post count. ```ts const relationCount = await prisma.user.findMany({ include: { _count: { select: { posts: true }, }, }, }) ``` ```code no-copy { id: 1, _count: { posts: 3 } }, { id: 2, _count: { posts: 2 } }, { id: 3, _count: { posts: 2 } }, { id: 4, _count: { posts: 0 } }, { id: 5, _count: { posts: 0 } } ``` ## Filter a list of relations When you use `select` or `include` to return a subset of the related data, you can **filter and sort the list of relations** inside the `select` or `include`. For example, the following query returns list of titles of the unpublished posts associated with the user: ```ts const result = await prisma.user.findFirst({ select: { posts: { where: { published: false, }, orderBy: { title: 'asc', }, select: { title: true, }, }, }, }) ``` You can also write the same query using `include` as follows: ```ts const result = await prisma.user.findFirst({ include: { posts: { where: { published: false, }, orderBy: { title: 'asc', }, }, }, }) ``` ## Nested writes A nested write allows you to write **relational data** to your database in **a single transaction**. Nested writes: - Provide **transactional guarantees** for creating, updating or deleting data across multiple tables in a single Prisma Client query. If any part of the query fails (for example, creating a user succeeds but creating posts fails), Prisma Client rolls back all changes. - Support any level of nesting supported by the data model. - Are available for [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) when using the model's create or update query. The following section shows the nested write options that are available per query. ### Create a related record You can create a record and one or more related records at the same time. The following query creates a `User` record and two related `Post` records: ```ts highlight=5-10;normal const result = await prisma.user.create({ data: { email: 'elsa@prisma.io', name: 'Elsa Prisma', //highlight-start posts: { create: [ { title: 'How to make an omelette' }, { title: 'How to eat an omelette' }, ], }, //highlight-end }, include: { posts: true, // Include all posts in the returned object }, }) ``` ```js no-copy { id: 29, name: 'Elsa', email: 'elsa@prisma.io', profileViews: 0, role: 'USER', coinflips: [], posts: [ { id: 22, title: 'How to make an omelette', published: true, authorId: 29, comments: null, views: 0, likes: 0 }, { id: 23, title: 'How to eat an omelette', published: true, authorId: 29, comments: null, views: 0, likes: 0 } ] } ``` ### Create a single record and multiple related records There are two ways to create or update a single record and multiple related records - for example, a user with multiple posts: - Use a nested [`create`](/orm/reference/prisma-client-reference#create-1) query - Use a nested [`createMany`](/orm/reference/prisma-client-reference#createmany-1) query In most cases, a nested `create` will be preferable unless the [`skipDuplicates` query option](/orm/reference/prisma-client-reference#nested-createmany-options) is required. Here's a quick table describing the differences between the two options: | Feature | `create` | `createMany` | Notes | | :------------------------------------ | :------- | :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Supports nesting additional relations | ✔ | ✘ \* | For example, you can create a user, several posts, and several comments per post in one query.
\* You can manually set a foreign key in a has-one relation - for example: `{ authorId: 9}` | | Supports 1-n relations | ✔ | ✔ | For example, you can create a user and multiple posts (one user has many posts) | | Supports m-n relations | ✔ | ✘ | For example, you can create a post and several categories (one post can have many categories, and one category can have many posts) | | Supports skipping duplicate records | ✘ | ✔ | Use `skipDuplicates` query option. | #### Using nested `create` The following query uses nested [`create`](/orm/reference/prisma-client-reference#create-1) to create: - One user - Two posts - One post category The example also uses a nested `include` to include all posts and post categories in the returned data. ```ts highlight=5-17;normal const result = await prisma.user.create({ data: { email: 'yvette@prisma.io', name: 'Yvette', //highlight-start posts: { create: [ { title: 'How to make an omelette', categories: { create: { name: 'Easy cooking', }, }, }, { title: 'How to eat an omelette' }, ], }, //highlight-end }, include: { // Include posts posts: { include: { categories: true, // Include post categories }, }, }, }) ``` ```js no-copy { "id": 40, "name": "Yvette", "email": "yvette@prisma.io", "profileViews": 0, "role": "USER", "coinflips": [], "testing": [], "city": null, "country": "Sweden", "posts": [ { "id": 66, "title": "How to make an omelette", "published": true, "authorId": 40, "comments": null, "views": 0, "likes": 0, "categories": [ { "id": 3, "name": "Easy cooking" } ] }, { "id": 67, "title": "How to eat an omelette", "published": true, "authorId": 40, "comments": null, "views": 0, "likes": 0, "categories": [] } ] } ``` Here's a visual representation of how a nested create operation can write to several tables in the database as once: ![](/img/orm/nested-create.png) #### Using nested `createMany` The following query uses a nested [`createMany`](/orm/reference/prisma-client-reference#create-1) to create: - One user - Two posts The example also uses a nested `include` to include all posts in the returned data. ```ts highlight=4-8;normal const result = await prisma.user.create({ data: { email: 'saanvi@prisma.io', //highlight-start posts: { createMany: { data: [{ title: 'My first post' }, { title: 'My second post' }], }, }, //highlight-end }, include: { posts: true, }, }) ``` ```js no-copy { "id": 43, "name": null, "email": "saanvi@prisma.io", "profileViews": 0, "role": "USER", "coinflips": [], "testing": [], "city": null, "country": "India", "posts": [ { "id": 70, "title": "My first post", "published": true, "authorId": 43, "comments": null, "views": 0, "likes": 0 }, { "id": 71, "title": "My second post", "published": true, "authorId": 43, "comments": null, "views": 0, "likes": 0 } ] } ``` Note that it is **not possible** to nest an additional `create` or `createMany` inside the highlighted query, which means that you cannot create a user, posts, and post categories at the same time. As a workaround, you can send a query to create the records that will be connected first, and then create the actual records. For example: ```ts const categories = await prisma.category.createManyAndReturn({ data: [ { name: 'Fun', }, { name: 'Technology', }, { name: 'Sports', } ], select: { id: true } }); const posts = await prisma.post.createManyAndReturn({ data: [{ title: "Funniest moments in 2024", categoryId: categories.filter(category => category.name === 'Fun')!.id }, { title: "Linux or macOS — what's better?", categoryId: categories.filter(category => category.name === 'Technology')!.id }, { title: "Who will win the next soccer championship?", categoryId: categories.filter(category => category.name === 'Sports')!.id }] }); ``` If you want to create _all_ records in a single database query, consider using a [`$transaction`](/orm/prisma-client/queries/transactions#the-transaction-api) or [type-safe, raw SQL](/orm/prisma-client/using-raw-sql/typedsql). ### Create multiple records and multiple related records You cannot access relations in a `createMany()` or `createManyAndReturn()` query, which means that you cannot create multiple users and multiple posts in a single nested write. The following is **not** possible: ```ts highlight=6-8,13-15;delete const createMany = await prisma.user.createMany({ data: [ { name: 'Yewande', email: 'yewande@prisma.io', //delete-start posts: { // Not possible to create posts! }, //delete-end }, { name: 'Noor', email: 'noor@prisma.io', //delete-start posts: { // Not possible to create posts! }, //delete-end }, ], }) ``` ### Connect multiple records The following query creates ([`create`](/orm/reference/prisma-client-reference#create) ) a new `User` record and connects that record ([`connect`](/orm/reference/prisma-client-reference#connect) ) to three existing posts: ```ts highlight=4-6;normal const result = await prisma.user.create({ data: { email: 'vlad@prisma.io', //highlight-start posts: { connect: [{ id: 8 }, { id: 9 }, { id: 10 }], }, //highlight-end }, include: { posts: true, // Include all posts in the returned object }, }) ``` ```js no-copy { id: 27, name: null, email: 'vlad@prisma.io', profileViews: 0, role: 'USER', coinflips: [], posts: [ { id: 10, title: 'An existing post', published: true, authorId: 27, comments: {}, views: 0, likes: 0 } ] } ``` > **Note**: Prisma Client throws an exception if any of the post records cannot be found: `connect: [{ id: 8 }, { id: 9 }, { id: 10 }]` ### Connect a single record You can [`connect`](/orm/reference/prisma-client-reference#connect) an existing record to a new or existing user. The following query connects an existing post (`id: 11`) to an existing user (`id: 9`) ```ts highlight=6-9;normal const result = await prisma.user.update({ where: { id: 9, }, data: { //highlight-start posts: { connect: { id: 11, }, //highlight-end }, }, include: { posts: true, }, }) ``` ### Connect _or_ create a record If a related record may or may not already exist, use [`connectOrCreate`](/orm/reference/prisma-client-reference#connectorcreate) to connect the related record: - Connect a `User` with the email address `viola@prisma.io` _or_ - Create a new `User` with the email address `viola@prisma.io` if the user does not already exist ```ts highlight=4-14;normal const result = await prisma.post.create({ data: { title: 'How to make croissants', //highlight-start author: { connectOrCreate: { where: { email: 'viola@prisma.io', }, create: { email: 'viola@prisma.io', name: 'Viola', }, }, }, //highlight-end }, include: { author: true, }, }) ``` ```js no-copy { id: 26, title: 'How to make croissants', published: true, authorId: 43, views: 0, likes: 0, author: { id: 43, name: 'Viola', email: 'viola@prisma.io', profileViews: 0, role: 'USER', coinflips: [] } } ``` ### Disconnect a related record To `disconnect` one out of a list of records (for example, a specific blog post) provide the ID or unique identifier of the record(s) to disconnect: ```ts highlight=6-8;normal const result = await prisma.user.update({ where: { id: 16, }, data: { //highlight-start posts: { disconnect: [{ id: 12 }, { id: 19 }], }, //highlight-end }, include: { posts: true, }, }) ``` ```js no-copy { id: 16, name: null, email: 'orla@prisma.io', profileViews: 0, role: 'USER', coinflips: [], posts: [] } ``` To `disconnect` _one_ record (for example, a post's author), use `disconnect: true`: ```ts highlight=6-8;normal const result = await prisma.post.update({ where: { id: 23, }, data: { //highlight-start author: { disconnect: true, }, //highlight-end }, include: { author: true, }, }) ``` ```js no-copy { id: 23, title: 'How to eat an omelette', published: true, authorId: null, comments: null, views: 0, likes: 0, author: null } ``` ### Disconnect all related records To [`disconnect`](/orm/reference/prisma-client-reference#disconnect) _all_ related records in a one-to-many relation (a user has many posts), `set` the relation to an empty list as shown: ```ts highlight=6-8;normal const result = await prisma.user.update({ where: { id: 16, }, data: { //highlight-start posts: { set: [], }, //highlight-end }, include: { posts: true, }, }) ``` ```js no-copy { id: 16, name: null, email: 'orla@prisma.io', profileViews: 0, role: 'USER', coinflips: [], posts: [] } ``` ### Delete all related records Delete all related `Post` records: ```ts highlight=6-8;normal const result = await prisma.user.update({ where: { id: 11, }, data: { //highlight-start posts: { deleteMany: {}, }, //highlight-end }, include: { posts: true, }, }) ``` ### Delete specific related records Update a user by deleting all unpublished posts: ```ts highlight=6-10;normal const result = await prisma.user.update({ where: { id: 11, }, data: { //highlight-start posts: { deleteMany: { published: false, }, }, //highlight-end }, include: { posts: true, }, }) ``` Update a user by deleting specific posts: ```ts highlight=6-8;normal const result = await prisma.user.update({ where: { id: 6, }, data: { //highlight-start posts: { deleteMany: [{ id: 7 }], }, //highlight-end }, include: { posts: true, }, }) ``` ### Update all related records (or filter) You can use a nested `updateMany` to update _all_ related records for a particular user. The following query unpublishes all posts for a specific user: ```ts highlight=6-15;normal const result = await prisma.user.update({ where: { id: 6, }, data: { //highlight-start posts: { updateMany: { where: { published: true, }, data: { published: false, }, }, }, //highlight-end }, include: { posts: true, }, }) ``` ### Update a specific related record ```ts highlight=6-15;normal const result = await prisma.user.update({ where: { id: 6, }, data: { //highlight-start posts: { update: { where: { id: 9, }, data: { title: 'My updated title', }, }, }, //highlight-end }, include: { posts: true, }, }) ``` ### Update _or_ create a related record The following query uses a nested `upsert` to update `"bob@prisma.io"` if that user exists, or create the user if they do not exist: ```ts highlight=6-17;normal const result = await prisma.post.update({ where: { id: 6, }, data: { //highlight-start author: { upsert: { create: { email: 'bob@prisma.io', name: 'Bob the New User', }, update: { email: 'bob@prisma.io', name: 'Bob the existing user', }, }, }, //highlight-end }, include: { author: true, }, }) ``` ### Add new related records to an existing record You can nest `create` or `createMany` inside an `update` to add new related records to an existing record. The following query adds two posts to a user with an `id` of 9: ```ts highlight=6-10;normal const result = await prisma.user.update({ where: { id: 9, }, data: { //highlight-start posts: { createMany: { data: [{ title: 'My first post' }, { title: 'My second post' }], }, }, //highlight-end }, include: { posts: true, }, }) ``` ## Relation filters ### Filter on "-to-many" relations Prisma Client provides the [`some`](/orm/reference/prisma-client-reference#some), [`every`](/orm/reference/prisma-client-reference#every), and [`none`](/orm/reference/prisma-client-reference#none) options to filter records by the properties of related records on the "-to-many" side of the relation. For example, filtering users based on properties of their posts. For example: | Requirement | Query option to use | | --------------------------------------------------------------------------------- | ----------------------------------- | | "I want a list of every `User` that has _at least one_ unpublished `Post` record" | `some` posts are unpublished | | "I want a list of every `User` that has _no_ unpublished `Post` records" | `none` of the posts are unpublished | | "I want a list of every `User` that has _only_ unpublished `Post` records" | `every` post is unpublished | For example, the following query returns `User` that meet the following criteria: - No posts with more than 100 views - All posts have less than, or equal to 50 likes ```ts const users = await prisma.user.findMany({ where: { //highlight-start posts: { none: { views: { gt: 100, }, }, every: { likes: { lte: 50, }, }, }, //highlight-end }, include: { posts: true, }, }) ``` ### Filter on "-to-one" relations Prisma Client provides the [`is`](/orm/reference/prisma-client-reference#is) and [`isNot`](/orm/reference/prisma-client-reference#isnot) options to filter records by the properties of related records on the "-to-one" side of the relation. For example, filtering posts based on properties of their author. For example, the following query returns `Post` records that meet the following criteria: - Author's name is not Bob - Author is older than 40 ```ts highlight=3-13;normal const users = await prisma.post.findMany({ where: { //highlight-start author: { isNot: { name: 'Bob', }, is: { age: { gt: 40, }, }, }, }, //highlight-end include: { author: true, }, }) ``` ### Filter on absence of "-to-many" records For example, the following query uses `none` to return all users that have zero posts: ```ts highlight=3-5;normal const usersWithZeroPosts = await prisma.user.findMany({ where: { //highlight-start posts: { none: {}, }, //highlight-end }, include: { posts: true, }, }) ``` ### Filter on absence of "-to-one" relations The following query returns all posts that don't have an author relation: ```js highlight=3;normal const postsWithNoAuthor = await prisma.post.findMany({ where: { //highlight-next-line author: null, // or author: { } }, include: { author: true, }, }) ``` ### Filter on presence of related records The following query returns all users with at least one post: ```ts highlight=3-5;normal const usersWithSomePosts = await prisma.user.findMany({ where: { //highlight-start posts: { some: {}, }, //highlight-end }, include: { posts: true, }, }) ``` ## Fluent API The fluent API lets you _fluently_ traverse the [relations](/orm/prisma-schema/data-model/relations) of your models via function calls. Note that the _last_ function call determines the return type of the entire query (the respective type annotations are added in the code snippets below to make that explicit). This query returns all `Post` records by a specific `User`: ```ts const postsByUser: Post[] = await prisma.user .findUnique({ where: { email: 'alice@prisma.io' } }) .posts() ``` This is equivalent to the following `findMany` query: ```ts const postsByUser = await prisma.post.findMany({ where: { author: { email: 'alice@prisma.io', }, }, }) ``` The main difference between the queries is that the fluent API call is translated into two separate database queries while the other one only generates a single query (see this [GitHub issue](https://github.com/prisma/prisma/issues/1984)) > **Note**: You can use the fact that `.findUnique({ where: { email: 'alice@prisma.io' } }).posts()` queries are automatically batched by the Prisma dataloader in Prisma Client to [avoid the n+1 problem in GraphQL resolvers](/orm/prisma-client/queries/query-optimization-performance#solving-n1-in-graphql-with-findunique-and-prisma-clients-dataloader). This request returns all categories by a specific post: ```ts const categoriesOfPost: Category[] = await prisma.post .findUnique({ where: { id: 1 } }) .categories() ``` Note that you can chain as many queries as you like. In this example, the chaining starts at `Profile` and goes over `User` to `Post`: ```ts const posts: Post[] = await prisma.profile .findUnique({ where: { id: 1 } }) .user() .posts() ``` The only requirement for chaining is that the previous function call must return only a _single object_ (e.g. as returned by a `findUnique` query or a "to-one relation" like `profile.user()`). The following query is **not possible** because `findMany` does not return a single object but a _list_: ```ts // This query is illegal const posts = await prisma.user.findMany().posts() ``` --- # Filtering and Sorting URL: https://www.prisma.io/docs/orm/prisma-client/queries/filtering-and-sorting Prisma Client supports [filtering](#filtering) with the `where` query option, and [sorting](#sorting) with the `orderBy` query option. ## Filtering Prisma Client allows you to filter records on any combination of model fields, [including related models](#filter-on-relations), and supports a variety of [filter conditions](#filter-conditions-and-operators). Some filter conditions use the SQL operators `LIKE` and `ILIKE` which may cause unexpected behavior in your queries. Please refer to [our filtering FAQs](#filtering-faqs) for more information. The following query: - Returns all `User` records with: - an email address that ends with `prisma.io` _and_ - at least one published post (a relation query) - Returns all `User` fields - Includes all related `Post` records where `published` equals `true` ```ts const result = await prisma.user.findMany({ where: { email: { endsWith: 'prisma.io', }, posts: { some: { published: true, }, }, }, include: { posts: { where: { published: true, }, }, }, }) ``` ```json5 no-copy [ { id: 1, name: 'Ellen', email: 'ellen@prisma.io', role: 'USER', posts: [ { id: 1, title: 'How to build a house', published: true, authorId: 1, }, { id: 2, title: 'How to cook kohlrabi', published: true, authorId: 1, }, ], }, ] ``` ### Filter conditions and operators Refer to Prisma Client's reference documentation for [a full list of operators](/orm/reference/prisma-client-reference#filter-conditions-and-operators) , such as `startsWith` and `contains`. #### Combining operators You can use operators (such as [`NOT`](/orm/reference/prisma-client-reference#not-1) and [`OR`](/orm/reference/prisma-client-reference#or) ) to filter by a combination of conditions. The following query returns all users whose `email` ends with `gmail.com` or `company.com`, but excludes any emails ending with `admin.company.com` ```ts const result = await prisma.user.findMany({ where: { OR: [ { email: { endsWith: 'gmail.com', }, }, { email: { endsWith: 'company.com' } }, ], NOT: { email: { endsWith: 'admin.company.com', }, }, }, select: { email: true, }, }) ``` ```json5 no-copy [{ email: 'alice@gmail.com' }, { email: 'bob@company.com' }] ``` ### Filter on null fields The following query returns all posts whose `content` field is `null`: ```ts const posts = await prisma.post.findMany({ where: { content: null, }, }) ``` ### Filter for non-null fields The following query returns all posts whose `content` field is **not** `null`: ```ts const posts = await prisma.post.findMany({ where: { content: { not: null }, }, }) ``` ### Filter on relations Prisma Client supports [filtering on related records](/orm/prisma-client/queries/relation-queries#relation-filters). For example, in the following schema, a user can have many blog posts: ```prisma highlight=5,12-13;normal model User { id Int @id @default(autoincrement()) name String? email String @unique //highlight-next-line posts Post[] // User can have many posts } model Post { id Int @id @default(autoincrement()) title String published Boolean @default(true) //highlight-start author User @relation(fields: [authorId], references: [id]) authorId Int //highlight-end } ``` The one-to-many relation between `User` and `Post` allows you to query users based on their posts - for example, the following query returns all users where _at least one_ post (`some`) has more than 10 views: ```ts const result = await prisma.user.findMany({ where: { posts: { some: { views: { gt: 10, }, }, }, }, }) ``` You can also query posts based on the properties of the author. For example, the following query returns all posts where the author's `email` contains `"prisma.io"`: ```ts const res = await prisma.post.findMany({ where: { author: { email: { contains: 'prisma.io', }, }, }, }) ``` ### Filter on scalar lists / arrays Scalar lists (for example, `String[]`) have a special set of [filter conditions](/orm/reference/prisma-client-reference#scalar-list-filters) - for example, the following query returns all posts where the `tags` array contains `databases`: ```ts const posts = await client.post.findMany({ where: { tags: { has: 'databases', }, }, }) ``` ### Case-insensitive filtering Case-insensitive filtering [is available as a feature for the PostgreSQL and MongoDB providers](/orm/prisma-client/queries/case-sensitivity#options-for-case-insensitive-filtering). MySQL, MariaDB and Microsoft SQL Server are case-insensitive by default, and do not require a Prisma Client feature to make case-insensitive filtering possible. To use case-insensitive filtering, add the `mode` property to a particular filter and specify `insensitive`: ```ts highlight=5;normal const users = await prisma.user.findMany({ where: { email: { endsWith: 'prisma.io', mode: 'insensitive', // Default value: default }, name: { equals: 'Archibald', // Default mode }, }, }) ``` See also: [Case sensitivity](/orm/prisma-client/queries/case-sensitivity) ### Filtering FAQs #### How does filtering work at the database level? For MySQL and PostgreSQL, Prisma Client utilizes the [`LIKE`](https://www.w3schools.com/sql/sql_like.asp) (and [`ILIKE`](https://www.postgresql.org/docs/current/functions-matching.html#FUNCTIONS-LIKE)) operator to search for a given pattern. The operators have built-in pattern matching using symbols unique to `LIKE`. The pattern-matching symbols include `%` for zero or more characters (similar to `*` in other regex implementations) and `_` for one character (similar to `.`) To match the literal characters, `%` or `_`, make sure you escape those characters. For example: ```ts const users = await prisma.user.findMany({ where: { name: { startsWith: '_benny', }, }, }) ``` The above query will match any user whose name starts with a character followed by `benny` such as `7benny` or `&benny`. If you instead wanted to find any user whose name starts with the literal string `_benny`, you could do: ```ts highlight=4 const users = await prisma.user.findMany({ where: { name: { startsWith: '\\_benny', // note that the `_` character is escaped, preceding `\` with `\` when included in a string }, }, }) ``` ## Sorting Use [`orderBy`](/orm/reference/prisma-client-reference#orderby) to sort a list of records or a nested list of records by a particular field or set of fields. For example, the following query returns all `User` records sorted by `role` and `name`, **and** each user's posts sorted by `title`: ```ts const usersWithPosts = await prisma.user.findMany({ orderBy: [ { role: 'desc', }, { name: 'desc', }, ], include: { posts: { orderBy: { title: 'desc', }, select: { title: true, }, }, }, }) ``` ```json no-copy [ { "email": "kwame@prisma.io", "id": 2, "name": "Kwame", "role": "USER", "posts": [ { "title": "Prisma in five minutes" }, { "title": "Happy Table Friends: Relations in Prisma" } ] }, { "email": "emily@prisma.io", "id": 5, "name": "Emily", "role": "USER", "posts": [ { "title": "Prisma Day 2020" }, { "title": "My first day at Prisma" }, { "title": "All about databases" } ] } ] ``` > **Note**: You can also [sort lists of nested records](/orm/prisma-client/queries/relation-queries#filter-a-list-of-relations) > to retrieve a single record by ID. ### Sort by relation You can also sort by properties of a relation. For example, the following query sorts all posts by the author's email address: ```ts const posts = await prisma.post.findMany({ orderBy: { author: { email: 'asc', }, }, }) ``` ### Sort by relation aggregate value In [2.19.0](https://github.com/prisma/prisma/releases/2.19.0) and later, you can sort by the **count of related records**. For example, the following query sorts users by the number of related posts: ```ts const getActiveUsers = await prisma.user.findMany({ take: 10, orderBy: { posts: { _count: 'desc', }, }, }) ``` > **Note**: It is not currently possible to [return the count of a relation](https://github.com/prisma/prisma/issues/5079). ### Sort by relevance (PostgreSQL and MySQL) In [3.5.0+](https://github.com/prisma/prisma/releases/3.5.0) for PostgreSQL and [3.8.0+](https://github.com/prisma/prisma/releases/3.8.0) for MySQL, you can sort records by relevance to the query using the `_relevance` keyword. This uses the relevance ranking functions from full text search features. This feature is further explain in [the PostgreSQL documentation](https://www.postgresql.org/docs/12/textsearch-controls.html) and [the MySQL documentation](https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html). **For PostgreSQL**, you need to enable order by relevance with the `fullTextSearchPostgres` [preview feature](/orm/prisma-client/queries/full-text-search): ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["fullTextSearchPostgres"] } ``` Ordering by relevance can be used either separately from or together with the `search` filter: `_relevance` is used to order the list, while `search` filters the unordered list. For example, the following query uses `_relevance` to filter by the term `developer` in the `bio` field, and then sorts the result by relevance in a _descending_ manner: ```ts const getUsersByRelevance = await prisma.user.findMany({ take: 10, orderBy: { _relevance: { fields: ['bio'], search: 'developer', sort: 'desc', }, }, }) ```
:::note Prior to Prisma ORM 5.16.0, enabling the `fullTextSearch` preview feature would rename the `OrderByWithRelationInput` TypeScript types to `OrderByWithRelationAndSearchRelevanceInput`. If you are using the Preview feature, you will need to update your type imports. ::: ### Sort with null records first or last :::info Notes: - This feature is generally available in version `4.16.0` and later. To use this feature in versions [`4.1.0`](https://github.com/prisma/prisma/releases/tag/4.1.0) to [`4.15.0`](https://github.com/prisma/prisma/releases/tag/4.15.0) the [Preview feature](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature) `orderByNulls` will need to be enabled. - This feature is not available for MongoDB. - You can only sort by nulls on optional [scalar](/orm/prisma-schema/data-model/models#scalar-fields) fields. If you try to sort by nulls on a required or [relation](/orm/prisma-schema/data-model/models#relation-fields) field, Prisma Client throws a [P2009 error](/orm/reference/error-reference#p2009). ::: You can sort the results so that records with `null` fields appear either first or last. If `name` is an optional field, then the following query using `last` sorts users by `name`, with `null` records at the end: ```ts const users = await prisma.user.findMany({ orderBy: { // highlight-next-line updatedAt: { sort: 'asc', nulls: 'last' }, }, }) ``` If you want the records with `null` values to appear at the beginning of the returned array, use `first`: ```ts const users = await prisma.user.findMany({ orderBy: { // highlight-next-line updatedAt: { sort: 'asc', nulls: 'first' }, }, }) ``` Note that `first` also is the default value, so if you omit the `null` option, `null` values will appear first in the returned array. ### Sorting FAQs #### Can I perform case-insensitive sorting? Follow [issue #841 on GitHub](https://github.com/prisma/prisma-client-js/issues/841). --- # Pagination URL: https://www.prisma.io/docs/orm/prisma-client/queries/pagination Prisma Client supports both offset pagination and cursor-based pagination. ## Offset pagination Offset pagination uses `skip` and `take` to skip a certain number of results and select a limited range. The following query skips the first 3 `Post` records and returns records 4 - 7: ```ts line-number const results = await prisma.post.findMany({ skip: 3, take: 4, }) ``` ![](/img/orm/offset-skip-take.png) To implement pages of results, you would just `skip` the number of pages multiplied by the number of results you show per page. ### ✔ Pros of offset pagination - You can jump to any page immediately. For example, you can `skip` 200 records and `take` 10, which simulates jumping straight to page 21 of the result set (the underlying SQL uses `OFFSET`). This is not possible with cursor-based pagination. - You can paginate the same result set in any sort order. For example, you can jump to page 21 of a list of `User` records sorted by first name. This is not possible with cursor-based pagination, which requires sorting by a unique, sequential column. ### ✘ Cons of offset pagination - Offset pagination **does not scale** at a database level. For example, if you skip 200,000 records and take the first 10, the database still has to traverse the first 200,000 records before returning the 10 that you asked for - this negatively affects performance. ### Use cases for offset pagination - Shallow pagination of a small result set. For example, a blog interface that allows you to filter `Post` records by author and paginate the results. ### Example: Filtering and offset pagination The following query returns all records where the `email` field contains `prisma.io`. The query skips the first 40 records and returns records 41 - 50. ```ts line-number const results = await prisma.post.findMany({ skip: 40, take: 10, where: { email: { contains: 'prisma.io', }, }, }) ``` ### Example: Sorting and offset pagination The following query returns all records where the `email` field contains `Prisma`, and sorts the result by the `title` field. The query skips the first 200 records and returns records 201 - 220. ```ts line-number const results = await prisma.post.findMany({ skip: 200, take: 20, where: { email: { contains: 'Prisma', }, }, orderBy: { title: 'desc', }, }) ``` ## Cursor-based pagination Cursor-based pagination uses `cursor` and `take` to return a limited set of results before or after a given **cursor**. A cursor bookmarks your location in a result set and must be a unique, sequential column - such as an ID or a timestamp. The following example returns the first 4 `Post` records that contain the word `"Prisma"` and saves the ID of the last record as `myCursor`: > **Note**: Since this is the first query, there is no cursor to pass in. ```ts showLineNumbers const firstQueryResults = await prisma.post.findMany({ take: 4, where: { title: { contains: 'Prisma' /* Optional filter */, }, }, orderBy: { id: 'asc', }, }) // Bookmark your location in the result set - in this // case, the ID of the last post in the list of 4. //highlight-start const lastPostInResults = firstQueryResults[3] // Remember: zero-based index! :) const myCursor = lastPostInResults.id // Example: 29 //highlight-end ``` The following diagram shows the IDs of the first 4 results - or page 1. The cursor for the next query is **29**: ![](/img/orm/cursor-1.png) The second query returns the first 4 `Post` records that contain the word `"Prisma"` **after the supplied cursor** (in other words - IDs that are larger than **29**): ```ts line-number const secondQueryResults = await prisma.post.findMany({ take: 4, skip: 1, // Skip the cursor //highlight-start cursor: { id: myCursor, }, //highlight-end where: { title: { contains: 'Prisma' /* Optional filter */, }, }, orderBy: { id: 'asc', }, }) const lastPostInResults = secondQueryResults[3] // Remember: zero-based index! :) const myCursor = lastPostInResults.id // Example: 52 ``` The following diagram shows the first 4 `Post` records **after** the record with ID **29**. In this example, the new cursor is **52**: ![](/img/orm/cursor-2.png) ### FAQ #### Do I always have to skip: 1? If you do not `skip: 1`, your result set will include your previous cursor. The first query returns four results and the cursor is **29**: ![](/img/orm/cursor-1.png) Without `skip: 1`, the second query returns 4 results after (and _including_) the cursor: ![](/img/orm/cursor-3.png) If you `skip: 1`, the cursor is not included: ![](/img/orm/cursor-2.png) You can choose to `skip: 1` or not depending on the pagination behavior that you want. #### Can I guess the value of the cursor? If you guess the value of the next cursor, you will page to an unknown location in your result set. Although IDs are sequential, you cannot predict the rate of increment (`2`, `20`, `32` is more likely than `1`, `2`, `3`, particularly in a filtered result set). #### Does cursor-based pagination use the concept of a cursor in the underlying database? No, cursor pagination does not use cursors in the underlying database ([e.g. PostgreSQL](https://www.postgresql.org/docs/9.2/plpgsql-cursors.html)). #### What happens if the cursor value does not exist? Using a nonexistent cursor returns `null`. Prisma Client does not try to locate adjacent values. ### ✔ Pros of cursor-based pagination - Cursor-based pagination **scales**. The underlying SQL does not use `OFFSET`, but instead queries all `Post` records with an ID greater than the value of `cursor`. ### ✘ Cons of cursor-based pagination - You must sort by your cursor, which has to be a unique, sequential column. - You cannot jump to a specific page using only a cursor. For example, you cannot accurately predict which cursor represents the start of page 400 (page size 20) without first requesting pages 1 - 399. ### Use cases for cursor-based pagination - Infinite scroll - for example, sort blog posts by date/time descending and request 10 blog posts at a time. - Paging through an entire result set in batches - for example, as part of a long-running data export. ### Example: Filtering and cursor-based pagination ```ts line-number const secondQuery = await prisma.post.findMany({ take: 4, cursor: { id: myCursor, }, //highlight-start where: { title: { contains: 'Prisma' /* Optional filter */, }, }, //highlight-end orderBy: { id: 'asc', }, }) ``` ### Sorting and cursor-based pagination Cursor-based pagination requires you to sort by a sequential, unique column such as an ID or a timestamp. This value - known as a cursor - bookmarks your place in the result set and allows you to request the next set. ### Example: Paging backwards with cursor-based pagination To page backwards, set `take` to a negative value. The following query returns 4 `Post` records with an `id` of less than 200, excluding the cursor: ```ts line-number const myOldCursor = 200 const firstQueryResults = await prisma.post.findMany({ take: -4, skip: 1, cursor: { id: myOldCursor, }, where: { title: { contains: 'Prisma' /* Optional filter */, }, }, orderBy: { id: 'asc', }, }) ``` --- # Aggregation, grouping, and summarizing URL: https://www.prisma.io/docs/orm/prisma-client/queries/aggregation-grouping-summarizing Prisma Client allows you to count records, aggregate number fields, and select distinct field values. ## Aggregate Prisma Client allows you to [`aggregate`](/orm/reference/prisma-client-reference#aggregate) on the **number** fields (such as `Int` and `Float`) of a model. The following query returns the average age of all users: ```ts const aggregations = await prisma.user.aggregate({ _avg: { age: true, }, }) console.log('Average age:' + aggregations._avg.age) ``` You can combine aggregation with filtering and ordering. For example, the following query returns the average age of users: - Ordered by `age` ascending - Where `email` contains `prisma.io` - Limited to the 10 users ```ts const aggregations = await prisma.user.aggregate({ _avg: { age: true, }, where: { email: { contains: 'prisma.io', }, }, orderBy: { age: 'asc', }, take: 10, }) console.log('Average age:' + aggregations._avg.age) ``` ### Aggregate values are nullable In [2.21.0](https://github.com/prisma/prisma/releases/tag/2.21.0) and later, aggregations on **nullable fields** can return a `number` or `null`. This excludes `count`, which always returns 0 if no records are found. Consider the following query, where `age` is nullable in the schema: ```ts const aggregations = await prisma.user.aggregate({ _avg: { age: true, }, _count: { age: true, }, }) ``` ```js no-copy { _avg: { age: null }, _count: { age: 9 } } ``` The query returns `{ _avg: { age: null } }` in either of the following scenarios: - There are no users - The value of every user's `age` field is `null` This allows you to differentiate between the true aggregate value (which could be zero) and no data. ## Group by Prisma Client's [`groupBy()`](/orm/reference/prisma-client-reference#groupby) allows you to **group records** by one or more field values - such as `country`, or `country` and `city` and **perform aggregations** on each group, such as finding the average age of people living in a particular city. `groupBy()` is a GA in [2.20.0](https://github.com/prisma/prisma/releases/2.20.0) and later. The following video uses `groupBy()` to summarize total COVID-19 cases by continent:
The following example groups all users by the `country` field and returns the total number of profile views for each country: ```ts const groupUsers = await prisma.user.groupBy({ by: ['country'], _sum: { profileViews: true, }, }) ``` ```js no-copy ;[ { country: 'Germany', _sum: { profileViews: 126 } }, { country: 'Sweden', _sum: { profileViews: 0 } }, ] ``` If you have a single element in the `by` option, you can use the following shorthand syntax to express your query: ```ts const groupUsers = await prisma.user.groupBy({ by: 'country', }) ``` ### `groupBy()` and filtering `groupBy()` supports two levels of filtering: `where` and `having`. #### Filter records with `where` Use `where` to filter all records **before grouping**. The following example groups users by country and sums profile views, but only includes users where the email address contains `prisma.io`: ```ts highlight=3-7;normal const groupUsers = await prisma.user.groupBy({ by: ['country'], //highlight-start where: { email: { contains: 'prisma.io', }, }, //highlight-end _sum: { profileViews: true, }, }) ``` #### Filter groups with `having` Use `having` to filter **entire groups** by an aggregate value such as the sum or average of a field, not individual records - for example, only return groups where the _average_ `profileViews` is greater than 100: ```ts highlight=11-17;normal const groupUsers = await prisma.user.groupBy({ by: ['country'], where: { email: { contains: 'prisma.io', }, }, _sum: { profileViews: true, }, //highlight-start having: { profileViews: { _avg: { gt: 100, }, }, }, //highlight-end }) ``` ##### Use case for `having` The primary use case for `having` is to filter on aggregations. We recommend that you use `where` to reduce the size of your data set as far as possible _before_ grouping, because doing so ✔ reduces the number of records the database has to return and ✔ makes use of indices. For example, the following query groups all users that are _not_ from Sweden or Ghana: ```ts highlight=4-6;normal const fd = await prisma.user.groupBy({ by: ['country'], where: { //highlight-start country: { notIn: ['Sweden', 'Ghana'], }, //highlight-end }, _sum: { profileViews: true, }, having: { profileViews: { _min: { gte: 10, }, }, }, }) ``` The following query technically achieves the same result, but excludes users from Ghana _after_ grouping. This does not confer any benefit and is not recommended practice. ```ts highlight=4-6,12-14;normal const groupUsers = await prisma.user.groupBy({ by: ['country'], where: { //highlight-start country: { not: 'Sweden', }, //highlight-end }, _sum: { profileViews: true, }, having: { //highlight-start country: { not: 'Ghana', }, //highlight-end profileViews: { _min: { gte: 10, }, }, }, }) ``` > **Note**: Within `having`, you can only filter on aggregate values _or_ fields available in `by`. ### `groupBy()` and ordering The following constraints apply when you combine `groupBy()` and `orderBy`: - You can `orderBy` fields that are present in `by` - You can `orderBy` aggregate (Preview in 2.21.0 and later) - If you use `skip` and/or `take` with `groupBy()`, you must also include `orderBy` in the query #### Order by aggregate group You can **order by aggregate group**. Prisma ORM added support for using `orderBy` with aggregated groups in relational databases in version [2.21.0](https://github.com/prisma/prisma/releases/2.21.0) and support for MongoDB in [3.4.0](https://github.com/prisma/prisma/releases/3.4.0). The following example sorts each `city` group by the number of users in that group (largest group first): ```ts const groupBy = await prisma.user.groupBy({ by: ['city'], _count: { city: true, }, orderBy: { _count: { city: 'desc', }, }, }) ``` ```js no-copy ;[ { city: 'Berlin', count: { city: 3 } }, { city: 'Paris', count: { city: 2 } }, { city: 'Amsterdam', count: { city: 1 } }, ] ``` #### Order by field The following query orders groups by country, skips the first two groups, and returns the 3rd and 4th group: ```ts const groupBy = await prisma.user.groupBy({ by: ['country'], _sum: { profileViews: true, }, orderBy: { country: 'desc', }, skip: 2, take: 2, }) ``` ### `groupBy()` FAQ #### Can I use `select` with `groupBy()`? You cannot use `select` with `groupBy()`. However, all fields included in `by` are automatically returned. #### What is the difference between using `where` and `having` with `groupBy()`? `where` filters all records before grouping, and `having` filters entire groups and supports filtering on an aggregate field value, such as the average or sum of a particular field in that group. #### What is the difference between `groupBy()` and `distinct`? Both `distinct` and `groupBy()` group records by one or more unique field values. `groupBy()` allows you to aggregate data within each group - for example, return the average number of views on posts from Denmark - whereas distinct does not. ## Count ### Count records Use [`count()`](/orm/reference/prisma-client-reference#count) to count the number of records or non-`null` field values. The following example query counts all users: ```ts const userCount = await prisma.user.count() ``` ### Count relations This feature is generally available in version [3.0.1](https://github.com/prisma/prisma/releases/3.0.1) and later. To use this feature in versions before 3.0.1 the [Preview feature](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature) `selectRelationCount` will need to be enabled. To return a count of relations (for example, a user's post count), use the `_count` parameter with a nested `select` as shown: ```ts const usersWithCount = await prisma.user.findMany({ include: { _count: { select: { posts: true }, }, }, }) ``` ```js no-copy { id: 1, _count: { posts: 3 } }, { id: 2, _count: { posts: 2 } }, { id: 3, _count: { posts: 2 } }, { id: 4, _count: { posts: 0 } }, { id: 5, _count: { posts: 0 } } ``` The `_count` parameter: - Can be used inside a top-level `include` _or_ `select` - Can be used with any query that returns records (including `delete`, `update`, and `findFirst`) - Can return [multiple relation counts](#return-multiple-relation-counts) - Can [filter relation counts](#filter-the-relation-count) (from version 4.3.0) #### Return a relations count with `include` The following query includes each user's post count in the results: ```ts const usersWithCount = await prisma.user.findMany({ include: { _count: { select: { posts: true }, }, }, }) ``` ```js no-copy { id: 1, _count: { posts: 3 } }, { id: 2, _count: { posts: 2 } }, { id: 3, _count: { posts: 2 } }, { id: 4, _count: { posts: 0 } }, { id: 5, _count: { posts: 0 } } ``` #### Return a relations count with `select` The following query uses `select` to return each user's post count _and no other fields_: ```ts const usersWithCount = await prisma.user.findMany({ select: { _count: { select: { posts: true }, }, }, }) ``` ```js no-copy { _count: { posts: 3 } } ``` #### Return multiple relation counts The following query returns a count of each user's `posts` and `recipes` and no other fields: ```ts const usersWithCount = await prisma.user.findMany({ select: { _count: { select: { posts: true, recipes: true, }, }, }, }) ``` ```js no-copy { _count: { posts: 3, recipes: 9 } } ``` #### Filter the relation count This feature is generally available in version `4.16.0` and later. To use this feature in versions [`4.3.0`](https://github.com/prisma/prisma/releases/tag/4.3.0) to [`4.15.0`](https://github.com/prisma/prisma/releases/tag/4.15.0) the [Preview feature](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature) `filteredRelationCount` will need to be enabled. Use `where` to filter the fields returned by the `_count` output type. You can do this on [scalar fields](/orm/prisma-schema/data-model/models#scalar-fields), [relation fields](/orm/prisma-schema/data-model/models#relation-fields) and fields of a [composite type](/orm/prisma-schema/data-model/models#defining-composite-types). For example, the following query returns all user posts with the title "Hello!": ```ts // Count all user posts with the title "Hello!" await prisma.user.findMany({ select: { _count: { select: { posts: { where: { title: 'Hello!' } }, }, }, }, }) ``` The following query finds all user posts with comments from an author named "Alice": ```ts // Count all user posts that have comments // whose author is named "Alice" await prisma.user.findMany({ select: { _count: { select: { posts: { where: { comments: { some: { author: { is: { name: 'Alice' } } } } }, }, }, }, }, }) ``` ### Count non-`null` field values In [2.15.0](https://github.com/prisma/prisma/releases/2.15.0) and later, you can count all records as well as all instances of non-`null` field values. The following query returns a count of: - All `User` records (`_all`) - All non-`null` `name` values (not distinct values, just values that are not `null`) ```ts const userCount = await prisma.user.count({ select: { _all: true, // Count all records name: true, // Count all non-null field values }, }) ``` ```js no-copy { _all: 30, name: 10 } ``` ### Filtered count `count` supports filtering. The following example query counts all users with more than 100 profile views: ```ts const userCount = await prisma.user.count({ where: { profileViews: { gte: 100, }, }, }) ``` The following example query counts a particular user's posts: ```ts const postCount = await prisma.post.count({ where: { authorId: 29, }, }) ``` ## Select distinct Prisma Client allows you to filter duplicate rows from a Prisma Query response to a [`findMany`](/orm/reference/prisma-client-reference#findmany) query using [`distinct`](/orm/reference/prisma-client-reference#distinct) . `distinct` is often used in combination with [`select`](/orm/reference/prisma-client-reference#select) to identify certain unique combinations of values in the rows of your table. The following example returns all fields for all `User` records with distinct `name` field values: ```ts const result = await prisma.user.findMany({ where: {}, distinct: ['name'], }) ``` The following example returns distinct `role` field values (for example, `ADMIN` and `USER`): ```ts const distinctRoles = await prisma.user.findMany({ distinct: ['role'], select: { role: true, }, }) ``` ```js no-copy ;[ { role: 'USER', }, { role: 'ADMIN', }, ] ``` ### `distinct` under the hood Prisma Client's `distinct` option does not use SQL `SELECT DISTINCT`. Instead, `distinct` uses: - A `SELECT` query - In-memory post-processing to select distinct It was designed in this way in order to **support `select` and `include`** as part of `distinct` queries. The following example selects distinct on `gameId` and `playerId`, ordered by `score`, in order to return **each player's highest score per game**. The query uses `include` and `select` to include additional data: - Select `score` (field on `Play`) - Select related player name (relation between `Play` and `User`) - Select related game name (relation between `Play` and `Game`)
Expand for sample schema ```prisma model User { id Int @id @default(autoincrement()) name String? play Play[] } model Game { id Int @id @default(autoincrement()) name String? play Play[] } model Play { id Int @id @default(autoincrement()) score Int? @default(0) playerId Int? player User? @relation(fields: [playerId], references: [id]) gameId Int? game Game? @relation(fields: [gameId], references: [id]) } ```
```ts const distinctScores = await prisma.play.findMany({ distinct: ['playerId', 'gameId'], orderBy: { score: 'desc', }, select: { score: true, game: { select: { name: true, }, }, player: { select: { name: true, }, }, }, }) ``` ```code no-copy [ { score: 900, game: { name: 'Pacman' }, player: { name: 'Bert Bobberton' } }, { score: 400, game: { name: 'Pacman' }, player: { name: 'Nellie Bobberton' } } ] ``` Without `select` and `distinct`, the query would return: ``` [ { gameId: 2, playerId: 5 }, { gameId: 2, playerId: 10 } ] ``` --- # Transactions and batch queries URL: https://www.prisma.io/docs/orm/prisma-client/queries/transactions A database transaction refers to a sequence of read/write operations that are _guaranteed_ to either succeed or fail as a whole. This section describes the ways in which the Prisma Client API supports transactions. ## Transactions overview Before Prisma ORM version 4.4.0, you could not set isolation levels on transactions. The isolation level in your database configuration always applied. Developers take advantage of the safety guarantees provided by the database by wrapping the operations in a transaction. These guarantees are often summarized using the ACID acronym: - **Atomic**: Ensures that either _all_ or _none_ operations of the transactions succeed. The transaction is either _committed_ successfully or _aborted_ and _rolled back_. - **Consistent**: Ensures that the states of the database before and after the transaction are _valid_ (i.e. any existing invariants about the data are maintained). - **Isolated**: Ensures that concurrently running transactions have the same effect as if they were running in serial. - **Durability**: Ensures that after the transaction succeeded, any writes are being stored persistently. While there's a lot of ambiguity and nuance to each of these properties (for example, consistency could actually be considered an _application-level responsibility_ rather than a database property or isolation is typically guaranteed in terms of stronger and weaker _isolation levels_), overall they serve as a good high-level guideline for expectations developers have when thinking about database transactions. > "Transactions are an abstraction layer that allows an application to pretend that certain concurrency problems and certain kinds of hardware and software faults don’t exist. A large class of errors is reduced down to a simple transaction abort, and the application just needs to try again." [Designing Data-Intensive Applications](https://dataintensive.net/), [Martin Kleppmann](https://bsky.app/profile/martin.kleppmann.com) Prisma Client supports six different ways of handling transactions for three different scenarios: | Scenario | Available techniques | | :------------------ | :-------------------------------------------------------------------------------------------------------------- | | Dependent writes |
  • Nested writes
| | Independent writes |
  • `$transaction([])` API
  • Batch operations
| | Read, modify, write |
  • Idempotent operations
  • Optimistic concurrency control
  • Interactive transactions
| The technique you choose depends on your particular use case. > **Note**: For the purposes of this guide, _writing_ to a database encompasses creating, updating, and deleting data. ## About transactions in Prisma Client Prisma Client provides the following options for using transactions: - [Nested writes](#nested-writes): use the Prisma Client API to process multiple operations on one or more related records inside the same transaction. - [Batch / bulk transactions](#batchbulk-operations): process one or more operations in bulk with `updateMany`, `deleteMany`, and `createMany`. - The `$transaction` API in Prisma Client: - [Sequential operations](#sequential-prisma-client-operations): pass an array of Prisma Client queries to be executed sequentially inside a transaction, using `$transaction(queries: PrismaPromise[]): Promise`. - [Interactive transactions](#interactive-transactions): pass a function that can contain user code including Prisma Client queries, non-Prisma code and other control flow to be executed in a transaction, using `$transaction(fn: (prisma: PrismaClient) => R, options?: object): R` ## Nested writes A [nested write](/orm/prisma-client/queries/relation-queries#nested-writes) lets you perform a single Prisma Client API call with multiple _operations_ that touch multiple [_related_](/orm/prisma-schema/data-model/relations) records. For example, creating a _user_ together with a _post_ or updating an _order_ together with an _invoice_. Prisma Client ensures that all operations succeed or fail as a whole. The following example demonstrates a nested write with `create`: ```ts // Create a new user with two posts in a // single transaction const newUser: User = await prisma.user.create({ data: { email: 'alice@prisma.io', posts: { create: [ { title: 'Join the Prisma Discord at https://pris.ly/discord' }, { title: 'Follow @prisma on Twitter' }, ], }, }, }) ``` The following example demonstrates a nested write with `update`: ```ts // Change the author of a post in a single transaction const updatedPost: Post = await prisma.post.update({ where: { id: 42 }, data: { author: { connect: { email: 'alice@prisma.io' }, }, }, }) ``` ## Batch/bulk operations The following bulk operations run as transactions: - `createMany()` - `createManyAndReturn()` - `updateMany()` - `updateManyAndReturn()` - `deleteMany()` > Refer to the section about [bulk operations](#bulk-operations) for more examples. ## The `$transaction` API The `$transaction` API can be used in two ways: - [Sequential operations](#sequential-prisma-client-operations): Pass an array of Prisma Client queries to be executed sequentially inside of a transaction. `$transaction(queries: PrismaPromise[]): Promise` - [Interactive transactions](#interactive-transactions): Pass a function that can contain user code including Prisma Client queries, non-Prisma code and other control flow to be executed in a transaction. `$transaction(fn: (prisma: PrismaClient) => R): R` ### Sequential Prisma Client operations The following query returns all posts that match the provided filter as well as a count of all posts: ```ts const [posts, totalPosts] = await prisma.$transaction([ prisma.post.findMany({ where: { title: { contains: 'prisma' } } }), prisma.post.count(), ]) ``` You can also use raw queries inside of a `$transaction`: ```ts import { selectUserTitles, updateUserName } from '@prisma/client/sql' const [userList, updateUser] = await prisma.$transaction([ prisma.$queryRawTyped(selectUserTitles()), prisma.$queryRawTyped(updateUserName(2)), ]) ``` ```ts const [findRawData, aggregateRawData, commandRawData] = await prisma.$transaction([ prisma.user.findRaw({ filter: { age: { $gt: 25 } }, }), prisma.user.aggregateRaw({ pipeline: [ { $match: { status: 'registered' } }, { $group: { _id: '$country', total: { $sum: 1 } } }, ], }), prisma.$runCommandRaw({ aggregate: 'User', pipeline: [ { $match: { name: 'Bob' } }, { $project: { email: true, _id: false } }, ], explain: false, }), ]) ``` Instead of immediately awaiting the result of each operation when it's performed, the operation itself is stored in a variable first which later is submitted to the database with a method called `$transaction`. Prisma Client will ensure that either all three `create` operations succeed or none of them succeed. > **Note**: Operations are executed according to the order they are placed in the transaction. Using a query in a transaction does not influence the order of operations in the query itself. > > Refer to the section about the [transactions API](#transaction-api) for more examples. From version 4.4.0, the sequential operations transaction API has a second parameter. You can use the following optional configuration option in this parameter: - `isolationLevel`: Sets the [transaction isolation level](#transaction-isolation-level). By default this is set to the value currently configured in your database. For example: ```ts await prisma.$transaction( [ prisma.resource.deleteMany({ where: { name: 'name' } }), prisma.resource.createMany({ data }), ], { isolationLevel: Prisma.TransactionIsolationLevel.Serializable, // optional, default defined by database configuration } ) ``` ### Interactive transactions #### Overview Sometimes you need more control over what queries execute within a transaction. Interactive transactions are meant to provide you with an escape hatch. Interactive transactions have been generally available from version 4.7.0. If you use interactive transactions in preview from version 2.29.0 to 4.6.1 (inclusive), you need to add the `interactiveTransactions` preview feature to the generator block of your Prisma schema. To use interactive transactions, you can pass an async function into [`$transaction`](#transaction-api). The first argument passed into this async function is an instance of Prisma Client. Below, we will call this instance `tx`. Any Prisma Client call invoked on this `tx` instance is encapsulated into the transaction. **Use interactive transactions with caution**. Keeping transactions open for a long time hurts database performance and can even cause deadlocks. Try to avoid performing network requests and executing slow queries inside your transaction functions. We recommend you get in and out as quick as possible! #### Example Let's look at an example: Imagine that you are building an online banking system. One of the actions to perform is to send money from one person to another. As experienced developers, we want to make sure that during the transfer, - the amount doesn't disappear - the amount isn't doubled This is a great use-case for interactive transactions because we need to perform logic in-between the writes to check the balance. In the example below, Alice and Bob each have $100 in their account. If they try to send more money than they have, the transfer is rejected. Alice is expected to be able to make 1 transfer for $100 while the other transfer would be rejected. This would result in Alice having $0 and Bob having $200. ```tsx import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() function transfer(from: string, to: string, amount: number) { return prisma.$transaction(async (tx) => { // 1. Decrement amount from the sender. const sender = await tx.account.update({ data: { balance: { decrement: amount, }, }, where: { email: from, }, }) // 2. Verify that the sender's balance didn't go below zero. if (sender.balance < 0) { throw new Error(`${from} doesn't have enough to send ${amount}`) } // 3. Increment the recipient's balance by amount const recipient = await tx.account.update({ data: { balance: { increment: amount, }, }, where: { email: to, }, }) return recipient }) } async function main() { // This transfer is successful await transfer('alice@prisma.io', 'bob@prisma.io', 100) // This transfer fails because Alice doesn't have enough funds in her account await transfer('alice@prisma.io', 'bob@prisma.io', 100) } main() ``` In the example above, both `update` queries run within a database transaction. When the application reaches the end of the function, the transaction is **committed** to the database. If your application encounters an error along the way, the async function will throw an exception and automatically **rollback** the transaction. To catch the exception, you can wrap `$transaction` in a try-catch block: ```js try { await prisma.$transaction(async (tx) => { // Code running in a transaction... }) } catch (err) { // Handle the rollback... } ``` #### Transaction options The transaction API has a second parameter. For interactive transactions, you can use the following optional configuration options in this parameter: - `maxWait`: The maximum amount of time Prisma Client will wait to acquire a transaction from the database. The default value is 2 seconds. - `timeout`: The maximum amount of time the interactive transaction can run before being canceled and rolled back. The default value is 5 seconds. - `isolationLevel`: Sets the [transaction isolation level](#transaction-isolation-level). By default this is set to the value currently configured in your database. For example: ```ts await prisma.$transaction( async (tx) => { // Code running in a transaction... }, { maxWait: 5000, // default: 2000 timeout: 10000, // default: 5000 isolationLevel: Prisma.TransactionIsolationLevel.Serializable, // optional, default defined by database configuration } ) ``` You can also set these globally on the constructor-level: ```ts const prisma = new PrismaClient({ transactionOptions: { isolationLevel: Prisma.TransactionIsolationLevel.Serializable, maxWait: 5000, // default: 2000 timeout: 10000, // default: 5000 }, }) ``` ### Transaction isolation level This feature is not available on MongoDB, because MongoDB does not support isolation levels. You can set the transaction [isolation level](https://www.prisma.io/dataguide/intro/database-glossary#isolation-levels) for transactions. This is available in the following Prisma ORM versions for interactive transactions from version 4.2.0, for sequential operations from version 4.4.0. In versions before 4.2.0 (for interactive transactions), or 4.4.0 (for sequential operations), you cannot configure the transaction isolation level at a Prisma ORM level. Prisma ORM does not explicitly set the isolation level, so the [isolation level configured in your database](#database-specific-information-on-isolation-levels) is used. #### Set the isolation level To set the transaction isolation level, use the `isolationLevel` option in the second parameter of the API. For sequential operations: ```ts await prisma.$transaction( [ // Prisma Client operations running in a transaction... ], { isolationLevel: Prisma.TransactionIsolationLevel.Serializable, // optional, default defined by database configuration } ) ``` For an interactive transaction: ```jsx await prisma.$transaction( async (prisma) => { // Code running in a transaction... }, { isolationLevel: Prisma.TransactionIsolationLevel.Serializable, // optional, default defined by database configuration maxWait: 5000, // default: 2000 timeout: 10000, // default: 5000 } ) ``` #### Supported isolation levels Prisma Client supports the following isolation levels if they are available in the underlying database: - `ReadUncommitted` - `ReadCommitted` - `RepeatableRead` - `Snapshot` - `Serializable` The isolation levels available for each database connector are as follows: | Database | `ReadUncommitted` | `ReadCommitted` | `RepeatableRead` | `Snapshot` | `Serializable` | | ----------- | ----------------- | --------------- | ---------------- | ---------- | -------------- | | PostgreSQL | ✔️ | ✔️ | ✔️ | No | ✔️ | | MySQL | ✔️ | ✔️ | ✔️ | No | ✔️ | | SQL Server | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | | CockroachDB | No | No | No | No | ✔️ | | SQLite | No | No | No | No | ✔️ | By default, Prisma Client sets the isolation level to the value currently configured in your database. The isolation levels configured by default in each database are as follows: | Database | Default | | ----------- | ---------------- | | PostgreSQL | `ReadCommitted` | | MySQL | `RepeatableRead` | | SQL Server | `ReadCommitted` | | CockroachDB | `Serializable` | | SQLite | `Serializable` | #### Database-specific information on isolation levels See the following resources: - [Transaction isolation levels in PostgreSQL](https://www.postgresql.org/docs/9.3/runtime-config-client.html#GUC-DEFAULT-TRANSACTION-ISOLATION) - [Transaction isolation levels in Microsoft SQL Server](https://learn.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-ver15) - [Transaction isolation levels in MySQL](https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html) CockroachDB and SQLite only support the `Serializable` isolation level. ### Transaction timing issues - The solution in this section does not apply to MongoDB, because MongoDB does not support [isolation levels](https://www.prisma.io/dataguide/intro/database-glossary#isolation-levels). - The timing issues discussed in this section do not apply to CockroachDB and SQLite, because these databases only support the highest `Serializable` isolation level. When two or more transactions run concurrently in certain [isolation levels](https://www.prisma.io/dataguide/intro/database-glossary#isolation-levels), timing issues can cause write conflicts or deadlocks, such as the violation of unique constraints. For example, consider the following sequence of events where Transaction A and Transaction B both attempt to execute a `deleteMany` and a `createMany` operation: 1. Transaction B: `createMany` operation creates a new set of rows. 1. Transaction B: The application commits transaction B. 1. Transaction A: `createMany` operation. 1. Transaction A: The application commits transaction A. The new rows conflict with the rows that transaction B added at step 2. This conflict can occur at the isolation level `ReadCommited`, which is the default isolation level in PostgreSQL and Microsoft SQL Server. To avoid this problem, you can set a higher isolation level (`RepeatableRead` or `Serializable`). You can set the isolation level on a transaction. This overrides your database isolation level for that transaction. To avoid transaction write conflicts and deadlocks on a transaction: 1. On your transaction, use the `isolationLevel` parameter to `Prisma.TransactionIsolationLevel.Serializable`. This ensures that your application commits multiple concurrent or parallel transactions as if they were run serially. When a transaction fails due to a write conflict or deadlock, Prisma Client returns a [P2034 error](/orm/reference/error-reference#p2034). 2. In your application code, add a retry around your transaction to handle any P2034 errors, as shown in this example: ```ts import { Prisma, PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { const MAX_RETRIES = 5 let retries = 0 let result while (retries < MAX_RETRIES) { try { result = await prisma.$transaction( [ prisma.user.deleteMany({ where: { /** args */ }, }), prisma.post.createMany({ data: { /** args */ }, }), ], { isolationLevel: Prisma.TransactionIsolationLevel.Serializable, } ) break } catch (error) { if (error.code === 'P2034') { retries++ continue } throw error } } } ``` ### Using `$transaction` within `Promise.all()` If you wrap a `$transaction` inside a call to `Promise.all()`, the queries inside the transaction will be executed _serially_ (i.e. one after another): ```ts await prisma.$transaction(async (prisma) => { await Promise.all([ prisma.user.findMany(), prisma.user.findMany(), prisma.user.findMany(), prisma.user.findMany(), prisma.user.findMany(), prisma.user.findMany(), prisma.user.findMany(), prisma.user.findMany(), prisma.user.findMany(), prisma.user.findMany(), ]) }) ``` This may be counterintuitive because `Promise.all()` usually _parallelizes_ the calls passed into it. The reason for this behaviour is that: - One transaction means that all queries inside it have to be run on the same connection. - A database connection can only ever execute one query at a time. - As one query blocks the connection while it is doing its work, putting a transaction into `Promise.all` effectively means that queries should be ran one after another. ## Dependent writes Writes are considered **dependent** on each other if: - Operations depend on the result of a preceding operation (for example, the database generating an ID) The most common scenario is creating a record and using the generated ID to create or update a related record. Examples include: - Creating a user and two related blog posts (a one-to-many relationship) - the author ID must be known before creating blog posts - Creating a team and assigning members (a many-to-many relationship) - the team ID must be known before assigning members Dependent writes must succeed together in order to maintain data consistency and prevent unexpected behavior, such as blog post without an author or a team without members. ### Nested writes Prisma Client's solution to dependent writes is the **nested writes** feature, which is supported by `create` and `update`. The following nested write creates one user and two blog posts: ```ts const nestedWrite = await prisma.user.create({ data: { email: 'imani@prisma.io', posts: { create: [ { title: 'My first day at Prisma' }, { title: 'How to configure a unique constraint in PostgreSQL' }, ], }, }, }) ``` If any operation fails, Prisma Client rolls back the entire transaction. Nested writes are not currently supported by top-level bulk operations like `client.user.deleteMany` and `client.user.updateMany`. #### When to use nested writes Consider using nested writes if: - ✔ You want to create two or more records related by ID at the same time (for example, create a blog post and a user) - ✔ You want to update and create records related by ID at the same time (for example, change a user's name and create a new blog post) :::tip If you [pre-compute your IDs, you can choose between a nested write or using the `$transaction([])` API](#scenario-pre-computed-ids-and-the-transaction-api). ::: #### Scenario: Sign-up flow Consider the Slack sign-up flow, which: 1. Creates a team 2. Adds one user to that team, which automatically becomes that team's administrator This scenario can be represented by the following schema - note that users can belong to many teams, and teams can have many users (a many-to-many relationship): ```prisma model Team { id Int @id @default(autoincrement()) name String members User[] // Many team members } model User { id Int @id @default(autoincrement()) email String @unique teams Team[] // Many teams } ``` The most straightforward approach is to create a team, then create and attach a user to that team: ```ts // Create a team const team = await prisma.team.create({ data: { name: 'Aurora Adventures', }, }) // Create a user and assign them to the team const user = await prisma.user.create({ data: { email: 'alice@prisma.io', team: { connect: { id: team.id, }, }, }, }) ``` However, this code has a problem - consider the following scenario: 1. Creating the team succeeds - "Aurora Adventures" is now taken 2. Creating and connecting the user fails - the team "Aurora Adventures" exists, but has no users 3. Going through the sign-up flow again and attempting to recreate "Aurora Adventures" fails - the team already exists Creating a team and adding a user should be one atomic operation that **succeeds or fails as a whole**. To implement atomic writes in a low-level database clients, you must wrap your inserts in `BEGIN`, `COMMIT` and `ROLLBACK` statements. Prisma Client solves the problem with [nested writes](/orm/prisma-client/queries/relation-queries#nested-writes). The following query creates a team, creates a user, and connects the records in a single transaction: ```ts const team = await prisma.team.create({ data: { name: 'Aurora Adventures', members: { create: { email: 'alice@prisma.io', }, }, }, }) ``` Furthermore, if an error occurs at any point, Prisma Client rolls back the entire transaction. #### Nested writes FAQs ##### Why can't I use the `$transaction([])` API to solve the same problem? The `$transaction([])` API does not allow you to pass IDs between distinct operations. In the following example, `createUserOperation.id` is not available yet: ```ts highlight=12;delete const createUserOperation = prisma.user.create({ data: { email: 'ebony@prisma.io', }, }) const createTeamOperation = prisma.team.create({ data: { name: 'Aurora Adventures', members: { connect: { //delete-next-line id: createUserOperation.id, // Not possible, ID not yet available }, }, }, }) await prisma.$transaction([createUserOperation, createTeamOperation]) ``` ##### Nested writes support nested updates, but updates are not dependent writes - should I use the `$transaction([])` API? It is correct to say that because you know the ID of the team, you can update the team and its team members independently within a `$transaction([])`. The following example performs both operations in a `$transaction([])`: ```ts const updateTeam = prisma.team.update({ where: { id: 1, }, data: { name: 'Aurora Adventures Ltd', }, }) const updateUsers = prisma.user.updateMany({ where: { teams: { some: { id: 1, }, }, name: { equals: null, }, }, data: { name: 'Unknown User', }, }) await prisma.$transaction([updateUsers, updateTeam]) ``` However, you can achieve the same result with a nested write: ```ts const updateTeam = await prisma.team.update({ where: { id: 1, }, data: { name: 'Aurora Adventures Ltd', // Update team name members: { updateMany: { // Update team members that do not have a name data: { name: 'Unknown User', }, where: { name: { equals: null, }, }, }, }, }, }) ``` ##### Can I perform multiple nested writes - for example, create two new teams and assign users? Yes, but this is a combination of scenarios and techniques: - Creating a team and assigning users is a dependent write - use nested writes - Creating all teams and users at the same time is an independent write because team/user combination #1 and team/user combination #2 are unrelated writes - use the `$transaction([])` API ```ts // Nested write const createOne = prisma.team.create({ data: { name: 'Aurora Adventures', members: { create: { email: 'alice@prisma.io', }, }, }, }) // Nested write const createTwo = prisma.team.create({ data: { name: 'Cool Crew', members: { create: { email: 'elsa@prisma.io', }, }, }, }) // $transaction([]) API await prisma.$transaction([createTwo, createOne]) ``` ## Independent writes Writes are considered **independent** if they do not rely on the result of a previous operation. The following groups of independent writes can occur in any order: - Updating the status field of a list of orders to "Dispatched" - Marking a list of emails as "Read" > **Note**: Independent writes may have to occur in a specific order if constraints are present - for example, you must delete blog posts before the blog author if the post have a mandatory `authorId` field. However, they are still considered independent writes because no operations depend on the _result_ of a previous operation, such as the database returning a generated ID. Depending on your requirements, Prisma Client has four options for handling independent writes that should succeed or fail together. ### Bulk operations Bulk writes allow you to write multiple records of the same type in a single transaction - if any operation fails, Prisma Client rolls back the entire transaction. Prisma Client currently supports: - `createMany()` - `createManyAndReturn()` - `updateMany()` - `updateManyAndReturn()` - `deleteMany()` #### When to use bulk operations Consider bulk operations as a solution if: - ✔ You want to update a batch of the _same type_ of record, like a batch of emails #### Scenario: Marking emails as read You are building a service like gmail.com, and your customer wants a **"Mark as read"** feature that allows users to mark all emails as read. Each update to the status of an email is an independent write because the emails do not depend on one another - for example, the "Happy Birthday! 🍰" email from your aunt is unrelated to the promotional email from IKEA. In the following schema, a `User` can have many received emails (a one-to-many relationship): ```ts model User { id Int @id @default(autoincrement()) email String @unique receivedEmails Email[] // Many emails } model Email { id Int @id @default(autoincrement()) user User @relation(fields: [userId], references: [id]) userId Int subject String body String unread Boolean } ``` Based on this schema, you can use `updateMany` to mark all unread emails as read: ```ts await prisma.email.updateMany({ where: { user: { id: 10, }, unread: true, }, data: { unread: false, }, }) ``` #### Can I use nested writes with bulk operations? No - neither `updateMany` nor `deleteMany` currently supports nested writes. For example, you cannot delete multiple teams and all of their members (a cascading delete): ```ts highlight=8;delete await prisma.team.deleteMany({ where: { id: { in: [2, 99, 2, 11], }, }, data: { //delete-next-line members: {}, // Cannot access members here }, }) ``` #### Can I use bulk operations with the `$transaction([])` API? Yes — for example, you can include multiple `deleteMany` operations inside a `$transaction([])`. ### `$transaction([])` API The `$transaction([])` API is generic solution to independent writes that allows you to run multiple operations as a single, atomic operation - if any operation fails, Prisma Client rolls back the entire transaction. Its also worth noting that operations are executed according to the order they are placed in the transaction. ```ts await prisma.$transaction([iRunFirst, iRunSecond, iRunThird]) ``` > **Note**: Using a query in a transaction does not influence the order of operations in the query itself. As Prisma Client evolves, use cases for the `$transaction([])` API will increasingly be replaced by more specialized bulk operations (such as `createMany`) and nested writes. #### When to use the `$transaction([])` API Consider the `$transaction([])` API if: - ✔ You want to update a batch that includes different types of records, such as emails and users. The records do not need to be related in any way. - ✔ You want to batch raw SQL queries (`$executeRaw`) - for example, for features that Prisma Client does not yet support. #### Scenario: Privacy legislation GDPR and other privacy legislation give users the right to request that an organization deletes all of their personal data. In the following example schema, a `User` can have many posts and private messages: ```prisma model User { id Int @id @default(autoincrement()) posts Post[] privateMessages PrivateMessage[] } model Post { id Int @id @default(autoincrement()) user User @relation(fields: [userId], references: [id]) userId Int title String content String } model PrivateMessage { id Int @id @default(autoincrement()) user User @relation(fields: [userId], references: [id]) userId Int message String } ``` If a user invokes the right to be forgotten, we must delete three records: the user record, private messages, and posts. It is critical that _all_ delete operations succeed together or not at all, which makes this a use case for a transaction. However, using a single bulk operation like `deleteMany` is not possible in this scenario because we need to delete across three models. Instead, we can use the `$transaction([])` API to run three operations together - two `deleteMany` and one `delete`: ```ts const id = 9 // User to be deleted const deletePosts = prisma.post.deleteMany({ where: { userId: id, }, }) const deleteMessages = prisma.privateMessage.deleteMany({ where: { userId: id, }, }) const deleteUser = prisma.user.delete({ where: { id: id, }, }) await prisma.$transaction([deletePosts, deleteMessages, deleteUser]) // Operations succeed or fail together ``` #### Scenario: Pre-computed IDs and the `$transaction([])` API Dependent writes are not supported by the `$transaction([])` API - if operation A relies on the ID generated by operation B, use [nested writes](#nested-writes). However, if you _pre-computed_ IDs (for example, by generating GUIDs), your writes become independent. Consider the sign-up flow from the nested writes example: ```ts await prisma.team.create({ data: { name: 'Aurora Adventures', members: { create: { email: 'alice@prisma.io', }, }, }, }) ``` Instead of auto-generating IDs, change the `id` fields of `Team` and `User` to a `String` (if you do not provide a value, a UUID is generated automatically). This example uses UUIDs: ```prisma highlight=2,9;delete|3,10;add model Team { //delete-next-line id Int @id @default(autoincrement()) //add-next-line id String @id @default(uuid()) name String members User[] } model User { //delete-next-line id Int @id @default(autoincrement()) //add-next-line id String @id @default(uuid()) email String @unique teams Team[] } ``` Refactor the sign-up flow example to use the `$transaction([])` API instead of nested writes: ```ts import { v4 } from 'uuid' const teamID = v4() const userID = v4() await prisma.$transaction([ prisma.user.create({ data: { id: userID, email: 'alice@prisma.io', team: { id: teamID, }, }, }), prisma.team.create({ data: { id: teamID, name: 'Aurora Adventures', }, }), ]) ``` Technically you can still use nested writes with pre-computed APIs if you prefer that syntax: ```ts import { v4 } from 'uuid' const teamID = v4() const userID = v4() await prisma.team.create({ data: { id: teamID, name: 'Aurora Adventures', members: { create: { id: userID, email: 'alice@prisma.io', team: { id: teamID, }, }, }, }, }) ``` There's no compelling reason to switch to manually generated IDs and the `$transaction([])` API if you are already using auto-generated IDs and nested writes. ## Read, modify, write In some cases you may need to perform custom logic as part of an atomic operation - also known as the [read-modify-write pattern](https://en.wikipedia.org/wiki/Read%E2%80%93modify%E2%80%93write). The following is an example of the read-modify-write pattern: - Read a value from the database - Run some logic to manipulate that value (for example, contacting an external API) - Write the value back to the database All operations should **succeed or fail together** without making unwanted changes to the database, but you do not necessarily need to use an actual database transaction. This section of the guide describes two ways to work with Prisma Client and the read-modify-write pattern: - Designing idempotent APIs - Optimistic concurrency control ### Idempotent APIs Idempotency is the ability to run the same logic with the same parameters multiple times with the same result: the **effect on the database** is the same whether you run the logic once or one thousand times. For example: - **NOT IDEMPOTENT**: Upsert (update-or-insert) a user in the database with email address `"letoya@prisma.io"`. The `User` table **does not** enforce unique email addresses. The effect on the database is different if you run the logic once (one user created) or ten times (ten users created). - **IDEMPOTENT**: Upsert (update-or-insert) a user in the database with the email address `"letoya@prisma.io"`. The `User` table **does** enforce unique email addresses. The effect on the database is the same if you run the logic once (one user created) or ten times (existing user is updated with the same input). Idempotency is something you can and should actively design into your application wherever possible. #### When to design an idempotent API - ✔ You need to be able to retry the same logic without creating unwanted side-effects in the databases #### Scenario: Upgrading a Slack team You are creating an upgrade flow for Slack that allows teams to unlock paid features. Teams can choose between different plans and pay per user, per month. You use Stripe as your payment gateway, and extend your `Team` model to store a `stripeCustomerId`. Subscriptions are managed in Stripe. ```prisma highlight=5;normal model Team { id Int @id @default(autoincrement()) name String User User[] //highlight-next-line stripeCustomerId String? } ``` The upgrade flow looks like this: 1. Count the number of users 2. Create a subscription in Stripe that includes the number of users 3. Associate the team with the Stripe customer ID to unlock paid features ```ts const teamId = 9 const planId = 'plan_id' // Count team members const numTeammates = await prisma.user.count({ where: { teams: { some: { id: teamId, }, }, }, }) // Create a customer in Stripe for plan-9454549 const customer = await stripe.customers.create({ externalId: teamId, plan: planId, quantity: numTeammates, }) // Update the team with the customer id to indicate that they are a customer // and support querying this customer in Stripe from our application code. await prisma.team.update({ data: { customerId: customer.id, }, where: { id: teamId, }, }) ``` This example has a problem: you can only run the logic _once_. Consider the following scenario: 1. Stripe creates a new customer and subscription, and returns a customer ID 2. Updating the team **fails** - the team is not marked as a customer in the Slack database 3. The customer is charged by Stripe, but paid features are not unlocked in Slack because the team lacks a valid `customerId` 4. Running the same code again either: - Results in an error because the team (defined by `externalId`) already exists - Stripe never returns a customer ID - If `externalId` is not subject to a unique constraint, Stripe creates yet another subscription (**not idempotent**) You cannot re-run this code in case of an error and you cannot change to another plan without being charged twice. The following refactor (highlighted) introduces a mechanism that checks if a subscription already exists, and either creates the description or updates the existing subscription (which will remain unchanged if the input is identical): ```ts highlight=12-27;normal // Calculate the number of users times the cost per user const numTeammates = await prisma.user.count({ where: { teams: { some: { id: teamId, }, }, }, }) //highlight-start // Find customer in Stripe let customer = await stripe.customers.get({ externalId: teamID }) if (customer) { // If team already exists, update customer = await stripe.customers.update({ externalId: teamId, plan: 'plan_id', quantity: numTeammates, //highlight-end }) } else { customer = await stripe.customers.create({ // If team does not exist, create customer externalId: teamId, plan: 'plan_id', quantity: numTeammates, }) } // Update the team with the customer id to indicate that they are a customer // and support querying this customer in Stripe from our application code. await prisma.team.update({ data: { customerId: customer.id, }, where: { id: teamId, }, }) ``` You can now retry the same logic multiple times with the same input without adverse effect. To further enhance this example, you can introduce a mechanism whereby the subscription is cancelled or temporarily deactivated if the update does not succeed after a set number of attempts. ### Optimistic concurrency control Optimistic concurrency control (OCC) is a model for handling concurrent operations on a single entity that does not rely on 🔒 locking. Instead, we **optimistically** assume that a record will remain unchanged in between reading and writing, and use a concurrency token (a timestamp or version field) to detect changes to a record. If a ❌ conflict occurs (someone else has changed the record since you read it), you cancel the transaction. Depending on your scenario, you can then: - Re-try the transaction (book another cinema seat) - Throw an error (alert the user that they are about to overwrite changes made by someone else) This section describes how to build your own optimistic concurrency control. See also: Plans for [application-level optimistic concurrency control on GitHub](https://github.com/prisma/prisma/issues/4988) - If you use version 4.4.0 or earlier, you cannot use optimistic concurrency control on `update` operations, because you cannot filter on non-unique fields. The `version` field you need to use with optimistic concurrency control is a non-unique field. - Since version 5.0.0 you are able to [filter on non-unique fields in `update` operations](/orm/reference/prisma-client-reference#filter-on-non-unique-fields-with-userwhereuniqueinput) so that optimistic concurrency control is being used. The feature was also available via the Preview flag `extendedWhereUnique` from versions 4.5.0 to 4.16.2. #### When to use optimistic concurrency control - ✔ You anticipate a high number of concurrent requests (multiple people booking cinema seats) - ✔ You anticipate that conflicts between those concurrent requests will be rare Avoiding locks in an application with a high number of concurrent requests makes the application more resilient to load and more scalable overall. Although locking is not inherently bad, locking in a high concurrency environment can lead to unintended consequences - even if you are locking individual rows, and only for a short amount of time. For more information, see: - [Why ROWLOCK Hints Can Make Queries Slower and Blocking Worse in SQL Server](https://kendralittle.com/2016/02/04/why-rowlock-hints-can-make-queries-slower-and-blocking-worse-in-sql-server/) #### Scenario: Reserving a seat at the cinema You are creating a booking system for a cinema. Each movie has a set number of seats. The following schema models movies and seats: ```ts model Seat { id Int @id @default(autoincrement()) userId Int? claimedBy User? @relation(fields: [userId], references: [id]) movieId Int movie Movie @relation(fields: [movieId], references: [id]) } model Movie { id Int @id @default(autoincrement()) name String @unique seats Seat[] } ``` The following sample code finds the first available seat and assigns that seat to a user: ```ts const movieName = 'Hidden Figures' // Find first available seat const availableSeat = await prisma.seat.findFirst({ where: { movie: { name: movieName, }, claimedBy: null, }, }) // Throw an error if no seats are available if (!availableSeat) { throw new Error(`Oh no! ${movieName} is all booked.`) } // Claim the seat await prisma.seat.update({ data: { claimedBy: userId, }, where: { id: availableSeat.id, }, }) ``` However, this code suffers from the "double-booking problem" - it is possible for two people to book the same seats: 1. Seat 3A returned to Sorcha (`findFirst`) 2. Seat 3A returned to Ellen (`findFirst`) 3. Seat 3A claimed by Sorcha (`update`) 4. Seat 3A claimed by Ellen (`update` - overwrites Sorcha's claim) Even though Sorcha has successfully booked the seat, the system ultimately stores Ellen's claim. To solve this problem with optimistic concurrency control, add a `version` field to the seat: ```prisma highlight=7;normal model Seat { id Int @id @default(autoincrement()) userId Int? claimedBy User? @relation(fields: [userId], references: [id]) movieId Int movie Movie @relation(fields: [movieId], references: [id]) //highlight-next-line version Int } ``` Next, adjust the code to check the `version` field before updating: ```ts highlight=19-38;normal const userEmail = 'alice@prisma.io' const movieName = 'Hidden Figures' // Find the first available seat // availableSeat.version might be 0 const availableSeat = await client.seat.findFirst({ where: { Movie: { name: movieName, }, claimedBy: null, }, }) if (!availableSeat) { throw new Error(`Oh no! ${movieName} is all booked.`) } //highlight-start // Only mark the seat as claimed if the availableSeat.version // matches the version we're updating. Additionally, increment the // version when we perform this update so all other clients trying // to book this same seat will have an outdated version. const seats = await client.seat.updateMany({ data: { claimedBy: userEmail, version: { increment: 1, }, }, where: { id: availableSeat.id, version: availableSeat.version, // This version field is the key; only claim seat if in-memory version matches database version, indicating that the field has not been updated }, }) if (seats.count === 0) { throw new Error(`That seat is already booked! Please try again.`) } //highlight-end ``` It is now impossible for two people to book the same seat: 1. Seat 3A returned to Sorcha (`version` is 0) 2. Seat 3A returned to Ellen (`version` is 0) 3. Seat 3A claimed by Sorcha (`version` is incremented to 1, booking succeeds) 4. Seat 3A claimed by Ellen (in-memory `version` (0) does not match database `version` (1) - booking does not succeed) ### Interactive transactions If you have an existing application, it can be a significant undertaking to refactor your application to use optimistic concurrency control. Interactive Transactions offers a useful escape hatch for cases like this. To create an interactive transaction, pass an async function into [$transaction](#transaction-api). The first argument passed into this async function is an instance of Prisma Client. Below, we will call this instance `tx`. Any Prisma Client call invoked on this `tx` instance is encapsulated into the transaction. In the example below, Alice and Bob each have $100 in their account. If they try to send more money than they have, the transfer is rejected. The expected outcome would be for Alice to make 1 transfer for $100 and the other transfer would be rejected. This would result in Alice having $0 and Bob having $200. ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function transfer(from: string, to: string, amount: number) { return await prisma.$transaction(async (tx) => { // 1. Decrement amount from the sender. const sender = await tx.account.update({ data: { balance: { decrement: amount, }, }, where: { email: from, }, }) // 2. Verify that the sender's balance didn't go below zero. if (sender.balance < 0) { throw new Error(`${from} doesn't have enough to send ${amount}`) } // 3. Increment the recipient's balance by amount const recipient = tx.account.update({ data: { balance: { increment: amount, }, }, where: { email: to, }, }) return recipient }) } async function main() { // This transfer is successful await transfer('alice@prisma.io', 'bob@prisma.io', 100) // This transfer fails because Alice doesn't have enough funds in her account await transfer('alice@prisma.io', 'bob@prisma.io', 100) } main() ``` In the example above, both `update` queries run within a database transaction. When the application reaches the end of the function, the transaction is **committed** to the database. If the application encounters an error along the way, the async function will throw an exception and automatically **rollback** the transaction. You can learn more about interactive transactions in this [section](#interactive-transactions). **Use interactive transactions with caution**. Keeping transactions open for a long time hurts database performance and can even cause deadlocks. Try to avoid performing network requests and executing slow queries inside your transaction functions. We recommend you get in and out as quick as possible! ## Conclusion Prisma Client supports multiple ways of handling transactions, either directly through the API or by supporting your ability to introduce optimistic concurrency control and idempotency into your application. If you feel like you have use cases in your application that are not covered by any of the suggested options, please open a [GitHub issue](https://github.com/prisma/prisma/issues/new/choose) to start a discussion. --- # Full-text search URL: https://www.prisma.io/docs/orm/prisma-client/queries/full-text-search Prisma Client supports full-text search for **PostgreSQL** databases in versions 2.30.0 and later, and **MySQL** databases in versions 3.8.0 and later. With full-text search (FTS) enabled, you can add search functionality to your application by searching for text within a database column. :::info In Prisma v6, FTS has been [promoted to General Availability on MySQL](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6#fulltextsearch). It still remains in Preview for PostgreSQL and requires using the [`fullTextSearchPostgres`](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6#full-text-search-on-postgresql) Preview feature flag. ::: ## Enabling full-text search for PostgreSQL The full-text search API is currently a Preview feature. To enable this feature, carry out the following steps: 1. Update the [`previewFeatures`](/orm/reference/preview-features) block in your schema to include the `fullTextSearchPostgres` preview feature flag: ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" previewFeatures = ["fullTextSearchPostgres"] } ``` 2. Generate Prisma Client: ```terminal copy npx prisma generate ``` After you regenerate your client, a new `search` field will be available on any `String` fields created on your models. For example, the following search will return all posts that contain the word 'cat'. ```ts // All posts that contain the word 'cat'. const result = await prisma.posts.findMany({ where: { body: { search: 'cat', }, }, }) ``` > **Note**: There currently is a [known issue](https://github.com/prisma/prisma/issues/23627) in the full-text search feature for PostgreSQL. If you observe slow search queries, you can [optimize your query with raw SQL](#full-text-search-with-raw-sql). ## Querying the database The `search` field uses the database's native querying capabilities under the hood. This means that the exact query operators available are also database-specific. ### PostgreSQL The following examples demonstrate the use of the PostgreSQL 'and' (`&`) and 'or' (`|`) operators: ```ts // All posts that contain the words 'cat' or 'dog'. const result = await prisma.posts.findMany({ where: { body: { search: 'cat | dog', }, }, }) // All drafts that contain the words 'cat' and 'dog'. const result = await prisma.posts.findMany({ where: { status: 'Draft', body: { search: 'cat & dog', }, }, }) ``` To get a sense of how the query format works, consider the following text: **"The quick brown fox jumps over the lazy dog"** Here's how the following queries would match that text: | Query | Match? | Explanation | | :-------------------------------------- | :----- | :-------------------------------------- | | `fox & dog` | Yes | The text contains 'fox' and 'dog' | | `dog & fox` | Yes | The text contains 'dog' and 'fox' | | `dog & cat` | No | The text contains 'dog' but not 'cat' | | `!cat` | Yes | 'cat' is not in the text | | `fox \| cat` | Yes | The text contains 'fox' or 'cat' | | `cat \| pig` | No | The text doesn't contain 'cat' or 'pig' | | `fox <-> dog` | Yes | 'dog' follows 'fox' in the text | | `dog <-> fox` | No | 'fox' doesn't follow 'dog' in the text | For the full range of supported operations, see the [PostgreSQL full text search documentation](https://www.postgresql.org/docs/12/functions-textsearch.html). ### MySQL The following examples demonstrate use of the MySQL 'and' (`+`) and 'not' (`-`) operators: ```ts // All posts that contain the words 'cat' or 'dog'. const result = await prisma.posts.findMany({ where: { body: { search: 'cat dog', }, }, }) // All posts that contain the words 'cat' and not 'dog'. const result = await prisma.posts.findMany({ where: { body: { search: '+cat -dog', }, }, }) // All drafts that contain the words 'cat' and 'dog'. const result = await prisma.posts.findMany({ where: { status: 'Draft', body: { search: '+cat +dog', }, }, }) ``` To get a sense of how the query format works, consider the following text: **"The quick brown fox jumps over the lazy dog"** Here's how the following queries would match that text: | Query | Match? | Description | | :------------- | :----- | :----------------------------------------------------- | | `+fox +dog` | Yes | The text contains 'fox' and 'dog' | | `+dog +fox` | Yes | The text contains 'dog' and 'fox' | | `+dog -cat` | Yes | The text contains 'dog' but not 'cat' | | `-cat` | No | The minus operator cannot be used on its own (see note below) | | `fox dog` | Yes | The text contains 'fox' or 'dog' | | `quic*` | Yes | The text contains a word starting with 'quic' | | `quick fox @2` | Yes | 'fox' starts within a 2 word distance of 'quick' | | `fox dog @2` | No | 'dog' does not start within a 2 word distance of 'fox' | | `"jumps over"` | Yes | The text contains the whole phrase 'jumps over' | > **Note**: The - operator acts only to exclude rows that are otherwise matched by other search terms. Thus, a boolean-mode search that contains only terms preceded by - returns an empty result. It does not return “all rows except those containing any of the excluded terms.” MySQL also has `>`, `<` and `~` operators for altering the ranking order of search results. As an example, consider the following two records: **1. "The quick brown fox jumps over the lazy dog"** **2. "The quick brown fox jumps over the lazy cat"** | Query | Result | Description | | :---------------- | :----------------------- | :------------------------------------------------------------------------------------------------------ | | `fox ~cat` | Return 1. first, then 2. | Return all records containing 'fox', but rank records containing 'cat' lower | | `fox (dog)` | Return 1. first, then 2. | Return all records containing 'fox', but rank records containing 'cat' lower than rows containing 'dog' | For the full range of supported operations, see the [MySQL full text search documentation](https://dev.mysql.com/doc/refman/8.0/en/fulltext-boolean.html). ## Sorting results by `_relevance` Sorting by relevance is only available for PostgreSQL and MySQL. In addition to [Prisma Client's default `orderBy` behavior](/orm/reference/prisma-client-reference#orderby), full-text search also adds sorting by relevance to a given string or strings. As an example, if you wanted to order posts by their relevance to the term `'database'` in their title, you could use the following: ```ts const posts = await prisma.post.findMany({ orderBy: { _relevance: { fields: ['title'], search: 'database', sort: 'asc' }, }, }) ``` ## Adding indexes ### PostgreSQL Prisma Client does not currently support using indexes to speed up full text search. There is an existing [GitHub Issue](https://github.com/prisma/prisma/issues/8950) for this. ### MySQL For MySQL, it is necessary to add indexes to any columns you search using the `@@fulltext` argument in the `schema.prisma` file. In the following example, one full text index is added to the `content` field of the `Blog` model, and another is added to both the `content` and `title` fields together: ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" } model Blog { id Int @unique content String title String @@fulltext([content]) @@fulltext([content, title]) } ``` The first index allows searching the `content` field for occurrences of the word 'cat': ```ts const result = await prisma.blogs.findMany({ where: { content: { search: 'cat', }, }, }) ``` The second index allows searching both the `content` and `title` fields for occurrences of the word 'cat' in the `content` and 'food' in the `title`: ```ts const result = await prisma.blogs.findMany({ where: { content: { search: 'cat', }, title: { search: 'food', }, }, }) ``` However, if you try to search on `title` alone, the search will fail with the error "Cannot find a fulltext index to use for the search" and the message code is `P2030`, because the search requires an index on both fields. ## Full-text search with raw SQL Full-text search is currently in Preview, and due to a [known issue](https://github.com/prisma/prisma/issues/23627), you might experience slow search queries. If so, you can optimize your query using [TypedSQL](/orm/prisma-client/using-raw-sql). ### PostgreSQL With [TypedSQL](/orm/prisma-client/using-raw-sql), you can use PostgreSQL's `to_tsvector` and `to_tsquery` to express your search query. ```sql SELECT * FROM "Blog" WHERE to_tsvector('english', "Blog"."content") @@ to_tsquery('english', ${term}); ``` ```ts import { fullTextSearch } from "@prisma/client/sql" const term = `cat` const result = await prisma.$queryRawTyped(fullTextSearch(term)) ``` > **Note**: Depending on your language preferences, you may exchange `english` against another language in the SQL statement. If you want to include a wildcard in your search term, you can do this as follows: ```sql SELECT * FROM "Blog" WHERE to_tsvector('english', "Blog"."content") @@ to_tsquery('english', ${term}); ``` ```ts //highlight-next-line const term = `cat:*` const result = await prisma.$queryRawTyped(fullTextSearch(term)) ``` ### MySQL In MySQL, you can express your search query as follows: ```sql SELECT * FROM Blog WHERE MATCH(content) AGAINST(${term} IN NATURAL LANGUAGE MODE); ``` ```ts const term = `cat` const result = await prisma.$queryRawTyped(fullTextSearch(term)) ``` --- # Custom validation URL: https://www.prisma.io/docs/orm/prisma-client/queries/custom-validation You can add runtime validation for your user input for Prisma Client queries in one of the following ways: - [Prisma Client extensions](/orm/prisma-client/client-extensions) - A custom function You can use any validation library you'd like. The Node.js ecosystem offers a number of high-quality, easy-to-use validation libraries to choose from including: [joi](https://github.com/sideway/joi), [validator.js](https://github.com/validatorjs/validator.js), [Yup](https://github.com/jquense/yup), [Zod](https://github.com/colinhacks/zod) and [Superstruct](https://github.com/ianstormtaylor/superstruct). ## Input validation with Prisma Client extensions This example adds runtime validation when creating and updating values using a Zod schema to check that the data passed to Prisma Client is valid. Query extensions do not currently work for nested operations. In this example, validations are only run on the top level data object passed to methods such as `prisma.product.create()`. Validations implemented this way do not automatically run for [nested writes](/orm/prisma-client/queries/relation-queries#nested-writes). ```ts copy import { PrismaClient, Prisma } from '@prisma/client' import { z } from 'zod' /** * Zod schema */ export const ProductCreateInput = z.object({ slug: z .string() .max(100) .regex(/^[a-z0-9]+(?:-[a-z0-9]+)*$/), name: z.string().max(100), description: z.string().max(1000), price: z .instanceof(Prisma.Decimal) .refine((price) => price.gte('0.01') && price.lt('1000000.00')), }) satisfies z.Schema /** * Prisma Client Extension */ const prisma = new PrismaClient().$extends({ query: { product: { create({ args, query }) { args.data = ProductCreateInput.parse(args.data) return query(args) }, update({ args, query }) { args.data = ProductCreateInput.partial().parse(args.data) return query(args) }, updateMany({ args, query }) { args.data = ProductCreateInput.partial().parse(args.data) return query(args) }, upsert({ args, query }) { args.create = ProductCreateInput.parse(args.create) args.update = ProductCreateInput.partial().parse(args.update) return query(args) }, }, }, }) async function main() { /** * Example usage */ // Valid product const product = await prisma.product.create({ data: { slug: 'example-product', name: 'Example Product', description: 'Lorem ipsum dolor sit amet', price: new Prisma.Decimal('10.95'), }, }) // Invalid product try { await prisma.product.create({ data: { slug: 'invalid-product', name: 'Invalid Product', description: 'Lorem ipsum dolor sit amet', price: new Prisma.Decimal('-1.00'), }, }) } catch (err: any) { console.log(err?.cause?.issues) } } main() ``` ```prisma copy datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Product { id String @id @default(cuid()) slug String name String description String price Decimal reviews Review[] } model Review { id String @id @default(cuid()) body String stars Int product Product @relation(fields: [productId], references: [id], onDelete: Cascade) productId String } ``` The above example uses a Zod schema to validate and parse data provided in a query at runtime before a record is written to the database. ## Input validation with a custom validation function Here's an example using [Superstruct](https://github.com/ianstormtaylor/superstruct) to validate that the data needed to signup a new user is correct: ```tsx import { PrismaClient, Prisma, User } from '@prisma/client' import { assert, object, string, size, refine } from 'superstruct' import isEmail from 'isemail' const prisma = new PrismaClient() // Runtime validation const Signup = object({ // string and a valid email address email: refine(string(), 'email', (v) => isEmail.validate(v)), // password is between 7 and 30 characters long password: size(string(), 7, 30), // first name is between 2 and 50 characters long firstName: size(string(), 2, 50), // last name is between 2 and 50 characters long lastName: size(string(), 2, 50), }) type Signup = Omit // Signup function async function signup(input: Signup): Promise { // Assert that input conforms to Signup, throwing with a helpful // error message if input is invalid. assert(input, Signup) return prisma.user.create({ data: input.user, }) } ``` The example above shows how you can create a custom type-safe `signup` function that ensures the input is valid before creating a user. ## Going further - Learn how you can use [Prisma Client extensions](/orm/prisma-client/client-extensions) to add input validation for your queries — [example](https://github.com/prisma/prisma-client-extensions/tree/main/input-validation). - Learn how you can organize your code better by moving the `signup` function into [a custom model](/orm/prisma-client/queries/custom-models). - There's an [outstanding feature request](https://github.com/prisma/prisma/issues/3528) to bake user validation into Prisma Client. If you'd like to see that happen, make sure to upvote that issue and share your use case! --- # Computed fields URL: https://www.prisma.io/docs/orm/prisma-client/queries/computed-fields Computed fields allow you to derive a new field based on existing data. A common example is when you want to compute a full name. In your database, you may only store the first and last name, but you can define a function that computes a full name by combining the first and last name. Computed fields are read-only and stored in your application's memory, not in your database. ## Using a Prisma Client extension The following example illustrates how to create a [Prisma Client extension](/orm/prisma-client/client-extensions) that adds a `fullName` computed field at runtime to the `User` model in a Prisma schema. ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient().$extends({ result: { user: { fullName: { needs: { firstName: true, lastName: true }, compute(user) { return `${user.firstName} ${user.lastName}` }, }, }, }, }) async function main() { /** * Example query containing the `fullName` computed field in the response */ const user = await prisma.user.findFirst() } main() ``` ```js no-copy { id: 1, firstName: 'Aurelia', lastName: 'Schneider', email: 'Jalen_Berge40@hotmail.com', fullName: 'Aurelia Schneider', } ``` ```prisma copy datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model User { id Int @id @default(autoincrement()) email String @unique firstName String lastName String posts Post[] } model Post { id Int @id @default(autoincrement()) title String published Boolean @default(true) content String? authorId Int? author User? @relation(fields: [authorId], references: [id]) } ``` The computed fields are type-safe and can return anything from a concatenated value to complex objects or functions that can act as an instance method for your models.
Instructions prior to Prisma ORM 4.16.0 :::warning With Prisma Client extensions Generally Available as of Prisma ORM version 4.16.0, the following steps are not recommended. Please use [a client extension](#using-a-prisma-client-extension) to accomplish this. ::: Prisma Client does not yet natively support computed fields, but, you can define a function that accepts a generic type as an input then extend that generic to ensure it conforms to a specific structure. Finally, you can return that generic with additional computed fields. Let's see how that might look: ```tsx // Define a type that needs a first and last name type FirstLastName = { firstName: string lastName: string } // Extend the T generic with the fullName attribute type WithFullName = T & { fullName: string } // Take objects that satisfy FirstLastName and computes a full name function computeFullName( user: User ): WithFullName { return { ...user, fullName: user.firstName + ' ' + user.lastName, } } async function main() { const user = await prisma.user.findUnique({ where: 1 }) const userWithFullName = computeFullName(user) } ``` ```js function computeFullName(user) { return { ...user, fullName: user.firstName + ' ' + user.lastName, } } async function main() { const user = await prisma.user.findUnique({ where: 1 }) const userWithFullName = computeFullName(user) } ``` In the TypeScript example above, a `User` generic has been defined that extends the `FirstLastName` type. This means that whatever you pass into `computeFullName` must contain `firstName` and `lastName` keys. A `WithFullName` return type has also been defined, which takes whatever `User` is and tacks on a `fullName` string attribute. With this function, any object that contains `firstName` and `lastName` keys can compute a `fullName`. Pretty neat, right?
### Going further - Learn how you can use [Prisma Client extensions](/orm/prisma-client/client-extensions) to add a computed field to your schema — [example](https://github.com/prisma/prisma-client-extensions/tree/main/computed-fields). - Learn how you can move the `computeFullName` function into [a custom model](/orm/prisma-client/queries/custom-models). - There's an [open feature request](https://github.com/prisma/prisma/issues/3394) to add native support to Prisma Client. If you'd like to see that happen, make sure to upvote that issue and share your use case! --- # Excluding fields URL: https://www.prisma.io/docs/orm/prisma-client/queries/excluding-fields By default Prisma Client returns all fields from a model. You can use [`select`](/orm/prisma-client/queries/select-fields) to narrow the result set, but that can be unwieldy if you have a large model and you only want to exclude a small number of fields. :::info As of Prisma ORM 6.2.0, excluding fields is supported via the `omit` option that you can pass to Prisma Client. From versions 5.16.0 through 6.1.0, you must use the `omitApi` Preview feature to access this option. ::: ## Excluding a field globally using `omit` The following is a type-safe way to exclude a field _globally_ (i.e. for _all_ queries against a given model): ```ts const prisma = new PrismaClient({ omit: { user: { password: true } } }) // The password field is excluded in all queries, including this one const user = await prisma.user.findUnique({ where: { id: 1 } }) ``` ```prisma model User { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt firstName String lastName String email String @unique password String } ``` ## Excluding a field locally using `omit` The following is a type-safe way to exclude a field _locally_ (i.e. for a _single_ query): ```ts const prisma = new PrismaClient() // The password field is excluded only in this query const user = await prisma.user.findUnique({ omit: { password: true }, where: { id: 1 } }) ``` ```prisma model User { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt firstName String lastName String email String @unique password String } ``` ## How to omit multiple fields Omitting multiple fields works the same as selecting multiple fields: add multiple key-value pairs to the omit option. Using the same schema as before, you could omit password and email with the following: ```tsx const prisma = new PrismaClient() // password and email are excluded const user = await prisma.user.findUnique({ omit: { email: true, password: true, }, where: { id: 1, }, }) ``` Multiple fields can be omitted locally and globally. ## How to select a previously omitted field If you [omit a field globally](#excluding-a-field-globally-using-omit), you can "override" by either selecting the field specifically or by setting `omit` to `false` in a query. ```tsx const user = await prisma.user.findUnique({ select: { firstName: true, lastName: true, password: true // The password field is now selected. }, where: { id: 1 } }) ``` ```tsx const user = await prisma.user.findUnique({ omit: { password: false // The password field is now selected. }, where: { id: 1 } }) ``` ## When to use `omit` globally or locally It's important to understand when to omit a field globally or locally: - If you are omitting a field in order to prevent it from accidentally being included in a query, it's best to omit it _globally_. For example: Globally omitting the `password` field from a `User` model so that sensitive information doesn't accidentally get exposed. - If you are omitting a field because it's not needed in a query, it's best to omit it _locally_. Local omit (when an `omit` option is provided in a query) only applies to the query it is defined in, while a global omit applies to every query made with the same Prisma Client instance, [unless a specific select is used or the omit is overridden](#how-to-select-a-previously-omitted-field). --- # Custom models URL: https://www.prisma.io/docs/orm/prisma-client/queries/custom-models As your application grows, you may find the need to group related logic together. We suggest either: - Creating static methods using a [Prisma Client extension](/orm/prisma-client/client-extensions) - Wrapping a model in a class - Extending Prisma Client model object ## Static methods with Prisma Client extensions The following example demonstrates how to create a Prisma Client extension that adds a `signUp` and `findManyByDomain` methods to a User model. ```tsx import bcrypt from 'bcryptjs' import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient().$extends({ model: { user: { async signUp(email: string, password: string) { const hash = await bcrypt.hash(password, 10) return prisma.user.create({ data: { email, password: { create: { hash, }, }, }, }) }, async findManyByDomain(domain: string) { return prisma.user.findMany({ where: { email: { endsWith: `@${domain}` } }, }) }, }, }, }) async function main() { // Example usage await prisma.user.signUp('user2@example2.com', 's3cret') await prisma.user.findManyByDomain('example2.com') } ``` ```prisma file="prisma/schema.prisma" copy datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model User { id String @id @default(cuid()) email String password Password? } model Password { hash String user User @relation(fields: [userId], references: [id], onDelete: Cascade) userId String @unique } ``` ## Wrap a model in a class In the example below, you'll see how you can wrap the `user` model in the Prisma Client within a `Users` class. ```tsx import { PrismaClient, User } from '@prisma/client' type Signup = { email: string firstName: string lastName: string } class Users { constructor(private readonly prismaUser: PrismaClient['user']) {} // Signup a new user async signup(data: Signup): Promise { // do some custom validation... return this.prismaUser.create({ data }) } } async function main() { const prisma = new PrismaClient() const users = new Users(prisma.user) const user = await users.signup({ email: 'alice@prisma.io', firstName: 'Alice', lastName: 'Prisma', }) } ``` With this new `Users` class, you can define custom functions like `signup`: Note that in the example above, you're only exposing a `signup` method from Prisma Client. The Prisma Client is hidden within the `Users` class, so you're no longer be able to call methods like `findMany` and `upsert`. This approach works well when you have a large application and you want to intentionally limit what your models can do. ## Extending Prisma Client model object But what if you don't want to hide existing functionality but still want to group custom functions together? In this case, you can use `Object.assign` to extend Prisma Client without limiting its functionality: ```tsx import { PrismaClient, User } from '@prisma/client' type Signup = { email: string firstName: string lastName: string } function Users(prismaUser: PrismaClient['user']) { return Object.assign(prismaUser, { /** * Signup the first user and create a new team of one. Return the User with * a full name and without a password */ async signup(data: Signup): Promise { return prismaUser.create({ data }) }, }) } async function main() { const prisma = new PrismaClient() const users = Users(prisma.user) const user = await users.signup({ email: 'alice@prisma.io', firstName: 'Alice', lastName: 'Prisma', }) const numUsers = await users.count() console.log(user, numUsers) } ``` Now you can use your custom `signup` method alongside `count`, `updateMany`, `groupBy()` and all of the other wonderful methods that Prisma Client provides. Best of all, it's all type-safe! ## Going further We recommend using [Prisma Client extensions](/orm/prisma-client/client-extensions) to extend your models with [custom model methods](https://github.com/prisma/prisma-client-extensions/tree/main/instance-methods). --- # Case sensitivity URL: https://www.prisma.io/docs/orm/prisma-client/queries/case-sensitivity Case sensitivity affects **filtering** and **sorting** of data, and is determined by your [database collation](#database-collation-and-case-sensitivity). Sorting and filtering data yields different results depending on your settings: | Action | Case sensitive | Case insensitive | | --------------- | -------------------------------------------- | -------------------------------------------- | | Sort ascending | `Apple`, `Banana`, `apple pie`, `banana pie` | `Apple`, `apple pie`, `Banana`, `banana pie` | | Match `"apple"` | `apple` | `Apple`, `apple` | If you use a **relational database connector**, [Prisma Client](/orm/prisma-client) respects your database collation. Options and recommendations for supporting **case-insensitive** filtering and sorting with Prisma Client depend on your [database provider](#options-for-case-insensitive-filtering). If you use the MongoDB connector, [Prisma Client](/orm/prisma-client/queries) uses RegEx rules to enable case-insensitive filtering. The connector _does not_ use [MongoDB collation](https://www.mongodb.com/docs/manual/reference/collation/). > **Note**: Follow the progress of [case-insensitive sorting on GitHub](https://github.com/prisma/prisma-client-js/issues/841). ## Database collation and case sensitivity In the context of Prisma Client, the following section refers to relational database connectors only. Collation specifies how data is **sorted and compared** in a database, which includes casing. Collation is something you choose when you set up a database. The following example demonstrates how to view the collation of a MySQL database: ```sql no-lines SELECT @@character_set_database, @@collation_database; ``` ```no-lines no-copy +--------------------------+----------------------+ | @@character_set_database | @@collation_database | +--------------------------+----------------------+ | utf8mb4 | utf8mb4_0900_ai_ci | +--------------------------+----------------------+ ``` The example collation, [`utf8mb4_0900_ai_ci`](https://dev.mysql.com/doc/refman/8.0/en/charset-collation-names.html), is: - Accent-insensitive (`ai`) - Case-insensitive (`ci`). This means that `prisMa` will match `prisma`, `PRISMA`, `priSMA`, and so on: ```sql no-lines SELECT id, email FROM User WHERE email LIKE "%prisMa%" ``` ```no-lines no-copy +----+-----------------------------------+ | id | email | +----+-----------------------------------+ | 61 | alice@prisma.io | | 49 | birgitte@prisma.io | +----+-----------------------------------+ ``` The same query with Prisma Client: ```ts const users = await prisma.user.findMany({ where: { email: { contains: 'prisMa', }, }, select: { id: true, name: true, }, }) ``` ## Options for case-insensitive filtering The recommended way to support case-insensitive filtering with Prisma Client depends on your underlying provider. ### PostgreSQL provider PostgreSQL uses [deterministic collation](https://www.postgresql.org/docs/current/collation.html#COLLATION-NONDETERMINISTIC) by default, which means that filtering is **case-sensitive**. To support case-insensitive filtering, use the `mode: 'insensitive'` property on a per-field basis. Use the `mode` property on a filter as shown: ```ts highlight=5;normal const users = await prisma.user.findMany({ where: { email: { endsWith: 'prisma.io', mode: 'insensitive', // Default value: default }, }, }) ``` See also: [Filtering (Case-insensitive filtering)](/orm/prisma-client/queries/filtering-and-sorting#case-insensitive-filtering) #### Caveats - You cannot use case-insensitive filtering with C collation - [`citext`](https://www.postgresql.org/docs/12/citext.html) columns are always case-insensitive and are not affected by `mode` #### Performance If you rely heavily on case-insensitive filtering, consider [creating indexes in the PostgreSQL database](https://www.postgresql.org/docs/current/indexes.html) to improve performance: - [Create an expression index](https://www.postgresql.org/docs/current/indexes-expressional.html) for Prisma Client queries that use `equals` or `not` - Use the `pg_trgm` module to [create a trigram-based index](https://www.postgresql.org/docs/12/pgtrgm.html#id-1.11.7.40.7) for Prisma Client queries that use `startsWith`, `endsWith`, `contains` (maps to`LIKE` / `ILIKE` in PostgreSQL) ### MySQL provider MySQL uses **case-insensitive collation** by default. Therefore, filtering with Prisma Client and MySQL is case-insensitive by default. `mode: 'insensitive'` property is not required and therefore not available in the generated Prisma Client API. #### Caveats - You _must_ use a case-insensitive (`_ci`) collation in order to support case-insensitive filtering. Prisma Client does no support the `mode` filter property for the MySQL provider. ### MongoDB provider To support case-insensitive filtering, use the `mode: 'insensitive'` property on a per-field basis: ```ts highlight=5;normal const users = await prisma.user.findMany({ where: { email: { endsWith: 'prisma.io', mode: 'insensitive', // Default value: default }, }, }) ``` The MongoDB uses a RegEx rule for case-insensitive filtering. ### SQLite provider By default, text fields created by Prisma Client in SQLite databases do not support case-insensitive filtering. In SQLite, only [case-insensitive comparisons of ASCII characters](https://www.sqlite.org/faq.html#q18) are possible. To enable limited support (ASCII only) for case-insensitive filtering on a per-column basis, you will need to add `COLLATE NOCASE` when you define a text column. #### Adding case-insensitive filtering to a new column. To add case-insensitive filtering to a new column, you will need to modify the migration file that is created by Prisma Client. Taking the following Prisma Schema model: ```prisma model User { id Int @id email String } ``` and using `prisma migrate dev --create-only` to create the following migration file: ```sql -- CreateTable CREATE TABLE "User" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "email" TEXT NOT NULL ); ``` You would need to add `COLLATE NOCASE` to the `email` column in order to make case-insensitive filtering possible: ```sql -- CreateTable CREATE TABLE "User" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, //highlight-next-line "email" TEXT NOT NULL COLLATE NOCASE ); ``` #### Adding case-insensitive filtering to an existing column. Since columns cannot be updated in SQLite, `COLLATE NOCASE` can only be added to an existing column by creating a blank migration file and migrating data to a new table. Taking the following Prisma Schema model: ```prisma model User { id Int @id email String } ``` and using `prisma migrate dev --create-only` to create an empty migration file, you will need to rename the current `User` table and create a new `User` table with `COLLATE NOCASE`. ```sql -- UpdateTable ALTER TABLE "User" RENAME TO "User_old"; CREATE TABLE "User" ( "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "email" TEXT NOT NULL COLLATE NOCASE ); INSERT INTO "User" (id, email) SELECT id, email FROM "User_old"; DROP TABLE "User_old"; ``` ### Microsoft SQL Server provider Microsoft SQL Server uses **case-insensitive collation** by default. Therefore, filtering with Prisma Client and Microsoft SQL Server is case-insensitive by default. `mode: 'insensitive'` property is not required and therefore not available in the generated Prisma Client API. --- # Query optimization URL: https://www.prisma.io/docs/orm/prisma-client/queries/query-optimization-performance This guide shows how to identify and optimize query performance, debug performance issues, and address common challenges. ## Debugging performance issues Several common practices can lead to slow queries and performance problems, such as: - Over-fetching data - Missing indexes - Not caching repeated queries - Performing full table scans :::info For more potential causes of performance issues, visit [this page](/optimize/recommendations). ::: [Prisma Optimize](/optimize) offers [recommendations](/optimize/recommendations) to identify and address the inefficiencies listed above and more, helping to improve query performance. To get started, follow the [integration guide](/optimize/getting-started) and add Prisma Optimize to your project to begin diagnosing slow queries.
:::tip You can also [log query events at the client level](/orm/prisma-client/observability-and-logging/logging#event-based-logging) to view the generated queries, their parameters, and execution times. If you are particularly focused on monitoring query duration, consider using [logging middleware](/orm/prisma-client/client-extensions/middleware/logging-middleware). ::: ## Using bulk queries It is generally more performant to read and write large amounts of data in bulk - for example, inserting `50,000` records in batches of `1000` rather than as `50,000` separate inserts. `PrismaClient` supports the following bulk queries: - [`createMany()`](/orm/reference/prisma-client-reference#createmany) - [`createManyAndReturn()`](/orm/reference/prisma-client-reference#createmanyandreturn) - [`deleteMany()`](/orm/reference/prisma-client-reference#deletemany) - [`updateMany()`](/orm/reference/prisma-client-reference#updatemany) - [`updateManyAndReturn()`](/orm/reference/prisma-client-reference#updatemanyandreturn) - [`findMany()`](/orm/reference/prisma-client-reference#findmany) ## Reuse `PrismaClient` or use connection pooling to avoid database connection pool exhaustion Creating multiple instances of `PrismaClient` can exhaust your database connection pool, especially in serverless or edge environments, potentially slowing down other queries. Learn more in the [serverless challenge](/orm/prisma-client/setup-and-configuration/databases-connections#the-serverless-challenge). For applications with a traditional server, instantiate `PrismaClient` once and reuse it throughout your app instead of creating multiple instances. For example, instead of: ```ts file=query.ts async function getPosts() { const prisma = new PrismaClient() await prisma.post.findMany() } async function getUsers() { const prisma = new PrismaClient() await prisma.user.findMany() } ``` Define a single `PrismaClient` instance in a dedicated file and re-export it for reuse: ```ts file=db.ts export const prisma = new PrismaClient() ``` Then import the shared instance: ```ts file=query.ts import { prisma } from "db.ts" async function getPosts() { await prisma.post.findMany() } async function getUsers() { await prisma.user.findMany() } ``` For serverless development environments with frameworks that use HMR (Hot Module Replacement), ensure you properly handle a [single instance of Prisma in development](/orm/more/help-and-troubleshooting/nextjs-help#best-practices-for-using-prisma-client-in-development). ## Solving the n+1 problem The n+1 problem occurs when you loop through the results of a query and perform one additional query **per result**, resulting in `n` number of queries plus the original (n+1). This is a common problem with ORMs, particularly in combination with GraphQL, because it is not always immediately obvious that your code is generating inefficient queries. ### Solving n+1 in GraphQL with `findUnique()` and Prisma Client's dataloader
The Prisma Client dataloader automatically _batches_ `findUnique()` queries that occur in the same [tick](https://nodejs.org/en/learn/asynchronous-work/event-loop-timers-and-nexttick#processnexttick) and have the same `where` and `include` parameters if: - All criteria of the `where` filter are on scalar fields (unique or non-unique) of the same model you're querying. - All criteria use the `equal` filter, whether that's via the shorthand or explicit syntax `(where: { field: , field1: { equals: } })`. - No boolean operators or relation filters are present. Automatic batching of `findUnique()` is particularly useful in a **GraphQL context**. GraphQL runs a separate resolver function for every field, which can make it difficult to optimize a nested query. For example - the following GraphQL runs the `allUsers` resolver to get all users, and the `posts` resolver **once per user** to get each user's posts (n+1): ```js query { allUsers { id, posts { id } } } ``` The `allUsers` query uses `user.findMany(..)` to return all users: ```ts highlight=7;normal const Query = objectType({ name: 'Query', definition(t) { t.nonNull.list.nonNull.field('allUsers', { type: 'User', resolve: (_parent, _args, context) => { return context.prisma.user.findMany() }, }) }, }) ``` This results in a single SQL query: ```js { timestamp: 2021-02-19T09:43:06.332Z, query: 'SELECT `dev`.`User`.`id`, `dev`.`User`.`email`, `dev`.`User`.`name` FROM `dev`.`User` WHERE 1=1 LIMIT ? OFFSET ?', params: '[-1,0]', duration: 0, target: 'quaint::connector::metrics' } ``` However, the resolver function for `posts` is then invoked **once per user**. This results in a `findMany()` query **✘ per user** rather than a single `findMany()` to return all posts by all users (expand CLI output to see queries). ```ts highlight=10-13;normal; const User = objectType({ name: 'User', definition(t) { t.nonNull.int('id') t.string('name') t.nonNull.string('email') t.nonNull.list.nonNull.field('posts', { type: 'Post', resolve: (parent, _, context) => { return context.prisma.post.findMany({ where: { authorId: parent.id || undefined }, }) }, }) }, }) ``` ```js no-copy { timestamp: 2021-02-19T09:43:06.343Z, query: 'SELECT `dev`.`Post`.`id`, `dev`.`Post`.`createdAt`, `dev`.`Post`.`updatedAt`, `dev`.`Post`.`title`, `dev`.`Post`.`content`, `dev`.`Post`.`published`, `dev`.`Post`.`viewCount`, `dev`.`Post`.`authorId` FROM `dev`.`Post` WHERE `dev`.`Post`.`authorId` = ? LIMIT ? OFFSET ?', params: '[1,-1,0]', duration: 0, target: 'quaint::connector::metrics' } { timestamp: 2021-02-19T09:43:06.347Z, query: 'SELECT `dev`.`Post`.`id`, `dev`.`Post`.`createdAt`, `dev`.`Post`.`updatedAt`, `dev`.`Post`.`title`, `dev`.`Post`.`content`, `dev`.`Post`.`published`, `dev`.`Post`.`viewCount`, `dev`.`Post`.`authorId` FROM `dev`.`Post` WHERE `dev`.`Post`.`authorId` = ? LIMIT ? OFFSET ?', params: '[3,-1,0]', duration: 0, target: 'quaint::connector::metrics' } { timestamp: 2021-02-19T09:43:06.348Z, query: 'SELECT `dev`.`Post`.`id`, `dev`.`Post`.`createdAt`, `dev`.`Post`.`updatedAt`, `dev`.`Post`.`title`, `dev`.`Post`.`content`, `dev`.`Post`.`published`, `dev`.`Post`.`viewCount`, `dev`.`Post`.`authorId` FROM `dev`.`Post` WHERE `dev`.`Post`.`authorId` = ? LIMIT ? OFFSET ?', params: '[2,-1,0]', duration: 0, target: 'quaint::connector::metrics' } { timestamp: 2021-02-19T09:43:06.348Z, query: 'SELECT `dev`.`Post`.`id`, `dev`.`Post`.`createdAt`, `dev`.`Post`.`updatedAt`, `dev`.`Post`.`title`, `dev`.`Post`.`content`, `dev`.`Post`.`published`, `dev`.`Post`.`viewCount`, `dev`.`Post`.`authorId` FROM `dev`.`Post` WHERE `dev`.`Post`.`authorId` = ? LIMIT ? OFFSET ?', params: '[4,-1,0]', duration: 0, target: 'quaint::connector::metrics' } { timestamp: 2021-02-19T09:43:06.348Z, query: 'SELECT `dev`.`Post`.`id`, `dev`.`Post`.`createdAt`, `dev`.`Post`.`updatedAt`, `dev`.`Post`.`title`, `dev`.`Post`.`content`, `dev`.`Post`.`published`, `dev`.`Post`.`viewCount`, `dev`.`Post`.`authorId` FROM `dev`.`Post` WHERE `dev`.`Post`.`authorId` = ? LIMIT ? OFFSET ?', params: '[5,-1,0]', duration: 0, target: 'quaint::connector::metrics' } // And so on ``` #### Solution 1: Batching queries with the fluent API Use `findUnique()` in combination with [the fluent API](/orm/prisma-client/queries/relation-queries#fluent-api) (`.posts()`) as shown to return a user's posts. Even though the resolver is called once per user, the Prisma dataloader in Prisma Client **✔ batches the `findUnique()` queries**. :::info It may seem counterintitive to use a `prisma.user.findUnique(...).posts()` query to return posts instead of `prisma.posts.findMany()` - particularly as the former results in two queries rather than one. The **only** reason you need to use the fluent API (`user.findUnique(...).posts()`) to return posts is that the dataloader in Prisma Client batches `findUnique()` queries and does not currently [batch `findMany()` queries](https://github.com/prisma/prisma/issues/1477). When the dataloader batches `findMany()` queries or your query has the `relationStrategy` set to `join`, you no longer need to use `findUnique()` with the fluent API in this way. ::: ```ts highlight=13-18;add|10-12;delete const User = objectType({ name: 'User', definition(t) { t.nonNull.int('id') t.string('name') t.nonNull.string('email') t.nonNull.list.nonNull.field('posts', { type: 'Post', resolve: (parent, _, context) => { //delete-start return context.prisma.post.findMany({ where: { authorId: parent.id || undefined }, }) //delete-end //add-start return context.prisma.user .findUnique({ where: { id: parent.id || undefined }, }) .posts() }, //add-end }) }, }) ``` ```js no-copy { timestamp: 2021-02-19T09:59:46.340Z, query: 'SELECT `dev`.`User`.`id`, `dev`.`User`.`email`, `dev`.`User`.`name` FROM `dev`.`User` WHERE 1=1 LIMIT ? OFFSET ?', params: '[-1,0]', duration: 0, target: 'quaint::connector::metrics' } { timestamp: 2021-02-19T09:59:46.350Z, query: 'SELECT `dev`.`User`.`id` FROM `dev`.`User` WHERE `dev`.`User`.`id` IN (?,?,?) LIMIT ? OFFSET ?', params: '[1,2,3,-1,0]', duration: 0, target: 'quaint::connector::metrics' } { timestamp: 2021-02-19T09:59:46.350Z, query: 'SELECT `dev`.`Post`.`id`, `dev`.`Post`.`createdAt`, `dev`.`Post`.`updatedAt`, `dev`.`Post`.`title`, `dev`.`Post`.`content`, `dev`.`Post`.`published`, `dev`.`Post`.`viewCount`, `dev`.`Post`.`authorId` FROM `dev`.`Post` WHERE `dev`.`Post`.`authorId` IN (?,?,?) LIMIT ? OFFSET ?', params: '[1,2,3,-1,0]', duration: 0, target: 'quaint::connector::metrics' } ``` If the `posts` resolver is invoked once per user, the dataloader in Prisma Client groups `findUnique()` queries with the same parameters and selection set. Each group is optimized into a single `findMany()`. #### Solution 2: Using JOINs to perform queries You can perform the query with a [database join](/orm/prisma-client/queries/relation-queries#relation-load-strategies-preview) by setting `relationLoadStrategy` to `"join"`, ensuring that only **one** query is executed against the database. ```ts const User = objectType({ name: 'User', definition(t) { t.nonNull.int('id') t.string('name') t.nonNull.string('email') t.nonNull.list.nonNull.field('posts', { type: 'Post', resolve: (parent, _, context) => { return context.prisma.post.findMany({ relationLoadStrategy: "join", where: { authorId: parent.id || undefined }, }) }, }) }, }) ``` ### n+1 in other contexts The n+1 problem is most commonly seen in a GraphQL context because you have to find a way to optimize a single query across multiple resolvers. However, you can just as easily introduce the n+1 problem by looping through results with `forEach` in your own code. The following code results in n+1 queries - one `findMany()` to get all users, and one `findMany()` **per user** to get each user's posts: ```ts // One query to get all users const users = await prisma.user.findMany({}) // One query PER USER to get all posts users.forEach(async (usr) => { const posts = await prisma.post.findMany({ where: { authorId: usr.id, }, }) // Do something with each users' posts }) ``` ```sql no-copy SELECT "public"."User"."id", "public"."User"."email", "public"."User"."name" FROM "public"."User" WHERE 1=1 OFFSET $1 SELECT "public"."Post"."id", "public"."Post"."title" FROM "public"."Post" WHERE "public"."Post"."authorId" = $1 OFFSET $2 SELECT "public"."Post"."id", "public"."Post"."title" FROM "public"."Post" WHERE "public"."Post"."authorId" = $1 OFFSET $2 SELECT "public"."Post"."id", "public"."Post"."title" FROM "public"."Post" WHERE "public"."Post"."authorId" = $1 OFFSET $2 SELECT "public"."Post"."id", "public"."Post"."title" FROM "public"."Post" WHERE "public"."Post"."authorId" = $1 OFFSET $2 /* ..and so on .. */ ``` This is not an efficient way to query. Instead, you can: - Use nested reads ([`include`](/orm/reference/prisma-client-reference#include) ) to return users and related posts - Use the [`in`](/orm/reference/prisma-client-reference#in) filter - Set the [`relationLoadStrategy`](/orm/prisma-client/queries/relation-queries#relation-load-strategies-preview) to `"join"` #### Solving n+1 with `include` You can use `include` to return each user's posts. This only results in **two** SQL queries - one to get users, and one to get posts. This is known as a [nested read](/orm/prisma-client/queries/relation-queries#nested-reads). ```ts const usersWithPosts = await prisma.user.findMany({ include: { posts: true, }, }) ``` ```sql no-copy SELECT "public"."User"."id", "public"."User"."email", "public"."User"."name" FROM "public"."User" WHERE 1=1 OFFSET $1 SELECT "public"."Post"."id", "public"."Post"."title", "public"."Post"."authorId" FROM "public"."Post" WHERE "public"."Post"."authorId" IN ($1,$2,$3,$4) OFFSET $5 ``` #### Solving n+1 with `in` If you have a list of user IDs, you can use the `in` filter to return all posts where the `authorId` is `in` that list of IDs: ```ts const users = await prisma.user.findMany({}) const userIds = users.map((x) => x.id) const posts = await prisma.post.findMany({ where: { authorId: { in: userIds, }, }, }) ``` ```sql no-copy SELECT "public"."User"."id", "public"."User"."email", "public"."User"."name" FROM "public"."User" WHERE 1=1 OFFSET $1 SELECT "public"."Post"."id", "public"."Post"."createdAt", "public"."Post"."updatedAt", "public"."Post"."title", "public"."Post"."content", "public"."Post"."published", "public"."Post"."authorId" FROM "public"."Post" WHERE "public"."Post"."authorId" IN ($1,$2,$3,$4) OFFSET $5 ``` #### Solving n+1 with `relationLoadStrategy: "join"` You can perform the query with a [database join](/orm/prisma-client/queries/relation-queries#relation-load-strategies-preview) by setting `relationLoadStrategy` to `"join"`, ensuring that only **one** query is executed against the database. ```ts const users = await prisma.user.findMany({}) const userIds = users.map((x) => x.id) const posts = await prisma.post.findMany({ relationLoadStrategy: "join", where: { authorId: { in: userIds, }, }, }) ``` --- # Queries URL: https://www.prisma.io/docs/orm/prisma-client/queries/index ## In this section --- # TypedSQL URL: https://www.prisma.io/docs/orm/prisma-client/using-raw-sql/typedsql ## Getting started with TypedSQL To start using TypedSQL in your Prisma project, follow these steps: 1. Ensure you have `@prisma/client` and `prisma` installed and updated to at least version `5.19.0`. ```terminal npm install @prisma/client@latest npm install -D prisma@latest ``` 1. Add the `typedSql` preview feature flag to your `schema.prisma` file: ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["typedSql"] } ``` 1. Create a `sql` directory inside your `prisma` directory. This is where you'll write your SQL queries. ```terminal mkdir -p prisma/sql ``` 1. Create a new `.sql` file in your `prisma/sql` directory. For example, `getUsersWithPosts.sql`. Note that the file name must be a valid JS identifier and cannot start with a `$`. 1. Write your SQL queries in your new `.sql` file. For example: ```sql title="prisma/sql/getUsersWithPosts.sql" SELECT u.id, u.name, COUNT(p.id) as "postCount" FROM "User" u LEFT JOIN "Post" p ON u.id = p."authorId" GROUP BY u.id, u.name ``` 1. Generate Prisma Client with the `sql` flag to ensure TypeScript functions and types for your SQL queries are created: :::warning Make sure that any pending migrations are applied before generating the client with the `sql` flag. ::: ```terminal prisma generate --sql ``` If you don't want to regenerate the client after every change, this command also works with the existing `--watch` flag: ```terminal prisma generate --sql --watch ``` 1. Now you can import and use your SQL queries in your TypeScript code: ```typescript title="/src/index.ts" import { PrismaClient } from '@prisma/client' import { getUsersWithPosts } from '@prisma/client/sql' const prisma = new PrismaClient() const usersWithPostCounts = await prisma.$queryRawTyped(getUsersWithPosts()) console.log(usersWithPostCounts) ``` ## Passing Arguments to TypedSQL Queries To pass arguments to your TypedSQL queries, you can use parameterized queries. This allows you to write flexible and reusable SQL statements while maintaining type safety. Here's how to do it: 1. In your SQL file, use placeholders for the parameters you want to pass. The syntax for placeholders depends on your database engine: For PostgreSQL, use the positional placeholders `$1`, `$2`, etc.: ```sql title="prisma/sql/getUsersByAge.sql" SELECT id, name, age FROM users WHERE age > $1 AND age < $2 ``` For MySQL, use the positional placeholders `?`: ```sql title="prisma/sql/getUsersByAge.sql" SELECT id, name, age FROM users WHERE age > ? AND age < ? ``` In SQLite, there are a number of different placeholders you can use. Postional placeholders (`$1`, `$2`, etc.), general placeholders (`?`), and named placeholders (`:minAge`, `:maxAge`, etc.) are all available. For this example, we'll use named placeholders `:minAge` and `:maxAge`: ```sql title="prisma/sql/getUsersByAge.sql" SELECT id, name, age FROM users WHERE age > :minAge AND age < :maxAge ``` :::note See below for information on how to [define argument types in your SQL files](#defining-argument-types-in-your-sql-files). ::: 1. When using the generated function in your TypeScript code, pass the arguments as additional parameters to `$queryRawTyped`: ```typescript title="/src/index.ts" import { PrismaClient } from '@prisma/client' import { getUsersByAge } from '@prisma/client/sql' const prisma = new PrismaClient() const minAge = 18 const maxAge = 30 const users = await prisma.$queryRawTyped(getUsersByAge(minAge, maxAge)) console.log(users) ``` By using parameterized queries, you ensure type safety and protect against SQL injection vulnerabilities. The TypedSQL generator will create the appropriate TypeScript types for the parameters based on your SQL query, providing full type checking for both the query results and the input parameters. ### Passing array arguments to TypedSQL TypedSQL supports passing arrays as arguments for PostgreSQL. Use PostgreSQL's `ANY` operator with an array parameter. ```sql title="prisma/sql/getUsersByIds.sql" SELECT id, name, email FROM users WHERE id = ANY($1) ``` ```typescript title="/src/index.ts" import { PrismaClient } from '@prisma/client' import { getUsersByIds } from '@prisma/client/sql' const prisma = new PrismaClient() const userIds = [1, 2, 3] const users = await prisma.$queryRawTyped(getUsersByIds(userIds)) console.log(users) ``` TypedSQL will generate the appropriate TypeScript types for the array parameter, ensuring type safety for both the input and the query results. :::note When passing array arguments, be mindful of the maximum number of placeholders your database supports in a single query. For very large arrays, you may need to split the query into multiple smaller queries. ::: ### Defining argument types in your SQL files Argument typing in TypedSQL is accomplished via specific comments in your SQL files. These comments are of the form: ```sql -- @param {Type} $N:alias optional description ``` Where `Type` is a valid database type, `N` is the position of the argument in the query, and `alias` is an optional alias for the argument that is used in the TypeScript type. As an example, if you needed to type a single string argument with the alias `name` and the description "The name of the user", you would add the following comment to your SQL file: ```sql -- @param {String} $1:name The name of the user ``` To indicate that a parameter is nullable, add a question mark after the alias: ```sql -- @param {String} $1:name? The name of the user (optional) ``` Currently accepted types are `Int`, `BigInt`, `Float`, `Boolean`, `String`, `DateTime`, `Json`, `Bytes`, `null`, and `Decimal`. Taking the [example from above](#passing-arguments-to-typedsql-queries), the SQL file would look like this: ```sql -- @param {Int} $1:minAge -- @param {Int} $2:maxAge SELECT id, name, age FROM users WHERE age > $1 AND age < $2 ``` The format of argument type definitions is the same regardless of the database engine. :::note Manually argument type definitions are not supported for array arguments. For these arguments, you will need to rely on the type inference provided by TypedSQL. ::: ## Examples For practical examples of how to use TypedSQL in various scenarios, please refer to the [Prisma Examples repo](https://github.com/prisma/prisma-examples). This repo contains a collection of ready-to-run Prisma example projects that demonstrate best practices and common use cases, including TypedSQL implementations. ## Limitations of TypedSQL ### Supported Databases TypedSQL supports modern versions of MySQL and PostgreSQL without any further configuration. For MySQL versions older than 8.0 and all SQLite versions, you will need to manually [describe argument types](#defining-argument-types-in-your-sql-files) in your SQL files. The types of inputs are inferred in all supported versions of PostgreSQL and MySQL 8.0 and later. TypedSQL does not work with MongoDB, as it is specifically designed for SQL databases. ### Active Database Connection Required TypedSQL requires an active database connection to function properly. This means you need to have a running database instance that Prisma can connect to when generating the client with the `--sql` flag. If a `directUrl` is provided in your Prisma configuration, TypedSQL will use that for the connection. ### Dynamic SQL Queries with Dynamic Columns TypedSQL does not natively support constructing SQL queries with dynamically added columns. When you need to create a query where the columns are determined at runtime, you must use the `$queryRaw` and `$executeRaw` methods. These methods allow for the execution of raw SQL, which can include dynamic column selections. **Example of a query using dynamic column selection:** ```typescript const columns = 'name, email, age'; // Columns determined at runtime const result = await prisma.$queryRawUnsafe( `SELECT ${columns} FROM Users WHERE active = true` ); ``` In this example, the columns to be selected are defined dynamically and included in the SQL query. While this approach provides flexibility, it requires careful attention to security, particularly to [avoid SQL injection vulnerabilities](/orm/prisma-client/using-raw-sql/raw-queries#sql-injection-prevention). Additionally, using raw SQL queries means foregoing the type-safety and DX of TypedSQL. ## Acknowledgements This feature was heavily inspired by [PgTyped](https://github.com/adelsz/pgtyped) and [SQLx](https://github.com/launchbadge/sqlx). Additionally, SQLite parsing is handled by SQLx. --- # Raw queries URL: https://www.prisma.io/docs/orm/prisma-client/using-raw-sql/raw-queries :::warning With Prisma ORM `5.19.0`, we have released [TypedSQL](/orm/prisma-client/using-raw-sql). TypedSQL is a new way to write SQL queries that are type-safe and even easier to add to your workflow. We strongly recommend using TypedSQL queries over the legacy raw queries described below whenever possible. ::: Prisma Client supports the option of sending raw queries to your database. You may wish to use raw queries if: - you want to run a heavily optimized query - you require a feature that Prisma Client does not yet support (please [consider raising an issue](https://github.com/prisma/prisma/issues/new/choose)) Raw queries are available for all relational databases Prisma ORM supports. In addition, from version `3.9.0` raw queries are supported in MongoDB. For more details, see the relevant sections: - [Raw queries with relational databases](#raw-queries-with-relational-databases) - [Raw queries with MongoDB](#raw-queries-with-mongodb) ## Raw queries with relational databases For relational databases, Prisma Client exposes four methods that allow you to send raw queries. You can use: - `$queryRaw` to return actual records (for example, using `SELECT`). - `$executeRaw` to return a count of affected rows (for example, after an `UPDATE` or `DELETE`). - `$queryRawUnsafe` to return actual records (for example, using `SELECT`) using a raw string. - `$executeRawUnsafe` to return a count of affected rows (for example, after an `UPDATE` or `DELETE`) using a raw string. The methods with "Unsafe" in the name are a lot more flexible but are at **significant risk of making your code vulnerable to SQL injection**. The other two methods are safe to use with a simple template tag, no string building, and no concatenation. **However**, caution is required for more complex use cases as it is still possible to introduce SQL injection if these methods are used in certain ways. For more details, see the [SQL injection prevention](#sql-injection-prevention) section below. > **Note**: All methods in the above list can only run **one** query at a time. You cannot append a second query - for example, calling any of them with `select 1; select 2;` will not work. ### `$queryRaw` `$queryRaw` returns actual database records. For example, the following `SELECT` query returns all fields for each record in the `User` table: ```ts no-lines const result = await prisma.$queryRaw`SELECT * FROM User`; ``` The method is implemented as a [tagged template](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates), which allows you to pass a template literal where you can easily insert your [variables](#using-variables). In turn, Prisma Client creates prepared statements that are safe from SQL injections: ```ts no-lines const email = "emelie@prisma.io"; const result = await prisma.$queryRaw`SELECT * FROM User WHERE email = ${email}`; ``` You can also use the [`Prisma.sql`](#tagged-template-helpers) helper, in fact, the `$queryRaw` method will **only accept** a template string or the `Prisma.sql` helper: ```ts no-lines const email = "emelie@prisma.io"; const result = await prisma.$queryRaw(Prisma.sql`SELECT * FROM User WHERE email = ${email}`); ``` If you use string building to incorporate untrusted input into queries passed to this method, then you open up the possibility for SQL injection attacks. SQL injection attacks can expose your data to modification or deletion. The preferred mechanism would be to include the text of the query at the point that you run this method. For more information on this risk and also examples of how to prevent it, see the [SQL injection prevention](#sql-injection-prevention) section below. #### Considerations Be aware that: - Template variables cannot be used inside SQL string literals. For example, the following query would **not** work: ```ts no-lines const name = "Bob"; await prisma.$queryRaw`SELECT 'My name is ${name}';`; ``` Instead, you can either pass the whole string as a variable, or use string concatenation: ```ts no-lines const name = "My name is Bob"; await prisma.$queryRaw`SELECT ${name};`; ``` ```ts no-lines const name = "Bob"; await prisma.$queryRaw`SELECT 'My name is ' || ${name};`; ``` - Template variables can only be used for data values (such as `email` in the example above). Variables cannot be used for identifiers such as column names, table names or database names, or for SQL keywords. For example, the following two queries would **not** work: ```ts no-lines const myTable = "user"; await prisma.$queryRaw`SELECT * FROM ${myTable};`; ``` ```ts no-lines const ordering = "desc"; await prisma.$queryRaw`SELECT * FROM Table ORDER BY ${ordering};`; ``` - Prisma maps any database values returned by `$queryRaw` and `$queryRawUnsafe` to their corresponding JavaScript types. [Learn more](#raw-query-type-mapping). - `$queryRaw` does not support dynamic table names in PostgreSQL databases. [Learn more](#dynamic-table-names-in-postgresql) #### Return type `$queryRaw` returns an array. Each object corresponds to a database record: ```json5 [ { id: 1, email: "emelie@prisma.io", name: "Emelie" }, { id: 2, email: "yin@prisma.io", name: "Yin" }, ] ``` You can also [type the results of `$queryRaw`](#typing-queryraw-results). #### Signature ```ts no-lines $queryRaw(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): PrismaPromise; ``` #### Typing `$queryRaw` results `PrismaPromise` uses a [generic type parameter `T`](https://www.typescriptlang.org/docs/handbook/generics.html). You can determine the type of `T` when you invoke the `$queryRaw` method. In the following example, `$queryRaw` returns `User[]`: ```ts // import the generated `User` type from the `@prisma/client` module import { User } from "@prisma/client"; const result = await prisma.$queryRaw`SELECT * FROM User`; // result is of type: `User[]` ``` > **Note**: If you do not provide a type, `$queryRaw` defaults to `unknown`. If you are selecting **specific fields** of the model or want to include relations, refer to the documentation about [leveraging Prisma Client's generated types](/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types#problem-using-variations-of-the-generated-model-type) if you want to make sure that the results are properly typed. #### Type caveats when using raw SQL When you type the results of `$queryRaw`, the raw data might not always match the suggested TypeScript type. For example, the following Prisma model includes a `Boolean` field named `published`: ```prisma highlight=3;normal model Post { id Int @id @default(autoincrement()) //highlight-next-line published Boolean @default(false) title String content String? } ``` The following query returns all posts. It then prints out the value of the `published` field for each `Post`: ```ts const result = await prisma.$queryRaw`SELECT * FROM Post`; result.forEach((x) => { console.log(x.published); }); ``` For regular CRUD queries, the Prisma Client query engine standardizes the return type for all databases. **Using the raw queries does not**. If the database provider is MySQL, the returned values are `1` or `0`. However, if the database provider is PostgreSQL, the values are `true` or `false`. > **Note**: Prisma sends JavaScript integers to PostgreSQL as `INT8`. This might conflict with your user-defined functions that accept only `INT4` as input. If you use `$queryRaw` in conjunction with a PostgreSQL database, update the input types to `INT8`, or cast your query parameters to `INT4`. #### Dynamic table names in PostgreSQL [It is not possible to interpolate table names](#considerations). This means that you cannot use dynamic table names with `$queryRaw`. Instead, you must use [`$queryRawUnsafe`](#queryrawunsafe), as follows: ```ts let userTable = "User"; let result = await prisma.$queryRawUnsafe(`SELECT * FROM ${userTable}`); ``` Note that if you use `$queryRawUnsafe` in conjunction with user inputs, you risk SQL injection attacks. [Learn more](#queryrawunsafe). ### `$queryRawUnsafe()` The `$queryRawUnsafe()` method allows you to pass a raw string (or template string) to the database. If you use this method with user inputs (in other words, `SELECT * FROM table WHERE columnx = ${userInput}`), then you open up the possibility for SQL injection attacks. SQL injection attacks can expose your data to modification or deletion.

Wherever possible you should use the `$queryRaw` method instead. When used correctly `$queryRaw` method is significantly safer but note that the `$queryRaw` method can also be made vulnerable in certain circumstances. For more information, see the [SQL injection prevention](#sql-injection-prevention) section below.
The following query returns all fields for each record in the `User` table: ```ts // import the generated `User` type from the `@prisma/client` module import { User } from "@prisma/client"; const result = await prisma.$queryRawUnsafe("SELECT * FROM User"); ``` You can also run a parameterized query. The following example returns all users whose email contains the string `emelie@prisma.io`: ```ts prisma.$queryRawUnsafe("SELECT * FROM users WHERE email = $1", "emelie@prisma.io"); ``` > **Note**: Prisma sends JavaScript integers to PostgreSQL as `INT8`. This might conflict with your user-defined functions that accept only `INT4` as input. If you use a parameterized `$queryRawUnsafe` query in conjunction with a PostgreSQL database, update the input types to `INT8`, or cast your query parameters to `INT4`. For more details on using parameterized queries, see the [parameterized queries](#parameterized-queries) section below. #### Signature ```ts no-lines $queryRawUnsafe(query: string, ...values: any[]): PrismaPromise; ``` ### `$executeRaw` `$executeRaw` returns the _number of rows affected by a database operation_, such as `UPDATE` or `DELETE`. This function does **not** return database records. The following query updates records in the database and returns a count of the number of records that were updated: ```ts const result: number = await prisma.$executeRaw`UPDATE User SET active = true WHERE emailValidated = true`; ``` The method is implemented as a [tagged template](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates), which allows you to pass a template literal where you can easily insert your [variables](#using-variables). In turn, Prisma Client creates prepared statements that are safe from SQL injections: ```ts const emailValidated = true; const active = true; const result: number = await prisma.$executeRaw`UPDATE User SET active = ${active} WHERE emailValidated = ${emailValidated};`; ``` If you use string building to incorporate untrusted input into queries passed to this method, then you open up the possibility for SQL injection attacks. SQL injection attacks can expose your data to modification or deletion. The preferred mechanism would be to include the text of the query at the point that you run this method. For more information on this risk and also examples of how to prevent it, see the [SQL injection prevention](#sql-injection-prevention) section below. #### Considerations Be aware that: - `$executeRaw` does not support multiple queries in a single string (for example, `ALTER TABLE` and `CREATE TABLE` together). - Prisma Client submits prepared statements, and prepared statements only allow a subset of SQL statements. For example, `START TRANSACTION` is not permitted. You can learn more about [the syntax that MySQL allows in Prepared Statements here](https://dev.mysql.com/doc/refman/8.0/en/sql-prepared-statements.html). - [`PREPARE` does not support `ALTER`](https://www.postgresql.org/docs/current/sql-prepare.html) - see the [workaround](#alter-limitation-postgresql). - Template variables cannot be used inside SQL string literals. For example, the following query would **not** work: ```ts no-lines const name = "Bob"; await prisma.$executeRaw`UPDATE user SET greeting = 'My name is ${name}';`; ``` Instead, you can either pass the whole string as a variable, or use string concatenation: ```ts no-lines const name = "My name is Bob"; await prisma.$executeRaw`UPDATE user SET greeting = ${name};`; ``` ```ts no-lines const name = "Bob"; await prisma.$executeRaw`UPDATE user SET greeting = 'My name is ' || ${name};`; ``` - Template variables can only be used for data values (such as `email` in the example above). Variables cannot be used for identifiers such as column names, table names or database names, or for SQL keywords. For example, the following two queries would **not** work: ```ts no-lines const myTable = "user"; await prisma.$executeRaw`UPDATE ${myTable} SET active = true;`; ``` ```ts no-lines const ordering = "desc"; await prisma.$executeRaw`UPDATE User SET active = true ORDER BY ${desc};`; ``` #### Return type `$executeRaw` returns a `number`. #### Signature ```ts $executeRaw(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): PrismaPromise; ``` ### `$executeRawUnsafe()` The `$executeRawUnsafe()` method allows you to pass a raw string (or template string) to the database. Like `$executeRaw`, it does **not** return database records, but returns the number of rows affected. If you use this method with user inputs (in other words, `SELECT * FROM table WHERE columnx = ${userInput}`), then you open up the possibility for SQL injection attacks. SQL injection attacks can expose your data to modification or deletion.

Wherever possible you should use the `$executeRaw` method instead. When used correctly `$executeRaw` method is significantly safer but note that the `$executeRaw` method can also be made vulnerable in certain circumstances. For more information, see the [SQL injection prevention](#sql-injection-prevention) section below.
The following example uses a template string to update records in the database. It then returns a count of the number of records that were updated: ```ts const emailValidated = true; const active = true; const result = await prisma.$executeRawUnsafe( `UPDATE User SET active = ${active} WHERE emailValidated = ${emailValidated}` ); ``` The same can be written as a parameterized query: ```ts const result = prisma.$executeRawUnsafe( "UPDATE User SET active = $1 WHERE emailValidated = $2", "yin@prisma.io", true ); ``` For more details on using parameterized queries, see the [parameterized queries](#parameterized-queries) section below. #### Signature ```ts no-lines $executeRawUnsafe(query: string, ...values: any[]): PrismaPromise; ``` ### Raw query type mapping Prisma maps any database values returned by `$queryRaw` and `$queryRawUnsafe`to their corresponding [JavaScript types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures). This behavior is the same as for regular Prisma query methods like `findMany()`. **Feature availability:** - In v3.14.x and v3.15.x, raw query type mapping was available with the preview feature `improvedQueryRaw`. We made raw query type mapping [Generally Available](/orm/more/releases#generally-available-ga) in version 4.0.0, so you do not need to use `improvedQueryRaw` in version 4.0.0 or later. - Before version 4.0.0, raw query type mapping was not available for SQLite. As an example, take a raw query that selects columns with `BigInt`, `Bytes`, `Decimal` and `Date` types from a table: ```ts const result = await prisma.$queryRaw`SELECT bigint, bytes, decimal, date FROM "Table";`; console.log(result); ``` ```terminal no-copy wrap { bigint: BigInt("123"), bytes: ), decimal: Decimal("12.34"), date: Date("") } ``` In the `result` object, the database values have been mapped to the corresponding JavaScript types. The following table shows the conversion between types used in the database and the JavaScript type returned by the raw query: | Database type | JavaScript type | | ----------------------- | ----------------------------------------------------------------------------------------------------------------------- | | Text | `String` | | 32-bit integer | `Number` | | 32-bit unsigned integer | `BigInt` | | Floating point number | `Number` | | Double precision number | `Number` | | 64-bit integer | `BigInt` | | Decimal / numeric | `Decimal` | | Bytes | `Uint8Array` ([before v6](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6#usage-of-buffer): `Buffer`) | | Json | `Object` | | DateTime | `Date` | | Date | `Date` | | Time | `Date` | | Uuid | `String` | | Xml | `String` | Note that the exact name for each database type will vary between databases – for example, the boolean type is known as `boolean` in PostgreSQL and `STRING` in CockroachDB. See the [Scalar types reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) for full details of type names for each database. ### Raw query typecasting behavior Raw queries with Prisma Client might require parameters to be in the expected types of the SQL function or query. Prisma Client does not do subtle, implicit casts. As an example, take the following query using PostgreSQL's `LENGTH` function, which only accepts the `text` type as an input: ```ts await prisma.$queryRaw`SELECT LENGTH(${42});`; ``` This query returns an error: ```terminal wrap // ERROR: function length(integer) does not exist // HINT: No function matches the given name and argument types. You might need to add explicit type casts. ``` The solution in this case is to explicitly cast `42` to the `text` type: ```ts await prisma.$queryRaw`SELECT LENGTH(${42}::text);`; ``` :::info **Feature availability:** This funtionality is [Generally Available](/orm/more/releases#generally-available-ga) since version 4.0.0. In v3.14.x and v3.15.x, it was available with the preview feature `improvedQueryRaw`. For the example above before version 4.0.0, Prisma ORM silently coerces `42` to `text` and does not require the explicit cast. On the other hand the following raw query now works correctly, returning an integer result, and failed before: ```ts await prisma.$queryRaw`SELECT ${1.5}::int as int`; // Now: [{ int: 2 }] // Before: db error: ERROR: incorrect binary data format in bind parameter 1 ``` ::: ### Transactions In 2.10.0 and later, you can use `.$executeRaw()` and `.$queryRaw()` inside a [transaction](/orm/prisma-client/queries/transactions). ### Using variables `$executeRaw` and `$queryRaw` are implemented as [**tagged templates**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#tagged_templates). Tagged templates are the recommended way to use variables with raw SQL in the Prisma Client. The following example includes a placeholder named `${userId}`: ```ts const userId = 42; const result = await prisma.$queryRaw`SELECT * FROM User WHERE id = ${userId};`; ``` ✔ Benefits of using the tagged template versions of `$queryRaw` and `$executeRaw` include: - Prisma Client escapes all variables. - Tagged templates are database-agnostic - you do not need to remember if variables should be written as `$1` (PostgreSQL) or `?` (MySQL). - [SQL Template Tag](https://github.com/blakeembrey/sql-template-tag) give you access to [useful helpers](#tagged-template-helpers). - Embedded, named variables are easier to read. > **Note**: You cannot pass a table or column name into a tagged template placeholder. For example, you cannot `SELECT ?` and pass in `*` or `id, name` based on some condition. #### Tagged template helpers Prisma Client specifically uses [SQL Template Tag](https://github.com/blakeembrey/sql-template-tag), which exposes a number of helpers. For example, the following query uses `join()` to pass in a list of IDs: ```ts import { Prisma } from "@prisma/client"; const ids = [1, 3, 5, 10, 20]; const result = await prisma.$queryRaw`SELECT * FROM User WHERE id IN (${Prisma.join(ids)})`; ``` The following example uses the `empty` and `sql` helpers to change the query depending on whether `userName` is empty: ```ts import { Prisma } from "@prisma/client"; const userName = ""; const result = await prisma.$queryRaw`SELECT * FROM User ${ userName ? Prisma.sql`WHERE name = ${userName}` : Prisma.empty // Cannot use "" or NULL here! }`; ``` #### `ALTER` limitation (PostgreSQL) PostgreSQL [does not support using `ALTER` in a prepared statement](https://www.postgresql.org/docs/current/sql-prepare.html), which means that the following queries **will not work**: ```ts await prisma.$executeRaw`ALTER USER prisma WITH PASSWORD "${password}"`; await prisma.$executeRaw(Prisma.sql`ALTER USER prisma WITH PASSWORD "${password}"`); ``` You can use the following query, but be aware that this is potentially **unsafe** as `${password}` is not escaped: ```ts await prisma.$executeRawUnsafe('ALTER USER prisma WITH PASSWORD "$1"', password}) ``` ### Unsupported types [`Unsupported` types](/orm/reference/prisma-schema-reference#unsupported) need to be cast to Prisma Client supported types before using them in `$queryRaw` or `$queryRawUnsafe`. For example, take the following model, which has a `location` field with an `Unsupported` type: ```tsx model Country { location Unsupported("point")? } ``` The following query on the unsupported field will **not** work: ```tsx await prisma.$queryRaw`SELECT location FROM Country;`; ``` Instead, cast `Unsupported` fields to any supported Prisma Client type, **if your `Unsupported` column supports the cast**. The most common type you may want to cast your `Unsupported` column to is `String`. For example, on PostgreSQL, this would map to the `text` type: ```tsx await prisma.$queryRaw`SELECT location::text FROM Country;`; ``` The database will thus provide a `String` representation of your data which Prisma Client supports. For details of supported Prisma types, see the [Prisma connector overview](/orm/overview/databases) for the relevant database. ## SQL injection prevention The ideal way to avoid SQL injection in Prisma Client is to use the ORM models to perform queries wherever possible. Where this is not possible and raw queries are required, Prisma Client provides various raw methods, but it is important to use these methods safely. This section will provide various examples of using these methods safely and unsafely. You can test these examples in the [Prisma Playground](https://playground.prisma.io/examples). ### In `$queryRaw` and `$executeRaw` #### Simple, safe use of `$queryRaw` and `$executeRaw` These methods can mitigate the risk of SQL injection by escaping all variables when you use tagged templates and sends all queries as prepared statements. ```ts $queryRaw`...`; // Tagged template $executeRaw`...`; // Tagged template ``` The following example is safe ✅ from SQL Injection: ```ts const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`; const result = await prisma.$queryRaw`SELECT id, name FROM "User" WHERE name = ${inputString}`; console.log(result); ``` #### Unsafe use of `$queryRaw` and `$executeRaw` However, it is also possible to use these methods in unsafe ways. One way is by artificially generating a tagged template that unsafely concatenates user input. The following example is vulnerable ❌ to SQL Injection: ```ts // Unsafely generate query text const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`; // SQL Injection const query = `SELECT id, name FROM "User" WHERE name = ${inputString}`; // Version for Typescript const stringsArray: any = [...[query]]; // Version for Javascript const stringsArray = [...[query]]; // Use the `raw` property to impersonate a tagged template stringsArray.raw = [query]; // Use queryRaw const result = await prisma.$queryRaw(stringsArray); console.log(result); ``` Another way to make these methods vulnerable is misuse of the `Prisma.raw` function. The following examples are all vulnerable ❌ to SQL Injection: ```ts const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`; const result = await prisma.$queryRaw`SELECT id, name FROM "User" WHERE name = ${Prisma.raw( inputString )}`; console.log(result); ``` ```ts const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`; const result = await prisma.$queryRaw( Prisma.raw(`SELECT id, name FROM "User" WHERE name = ${inputString}`) ); console.log(result); ``` ```ts const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`; const query = Prisma.raw(`SELECT id, name FROM "User" WHERE name = ${inputString}`); const result = await prisma.$queryRaw(query); console.log(result); ``` #### Safely using `$queryRaw` and `$executeRaw` in more complex scenarios ##### Building raw queries separate to query execution If you want to build your raw queries elsewhere or separate to your parameters you will need to use one of the following methods. In this example, the `sql` helper method is used to build the query text by safely including the variable. It is safe ✅ from SQL Injection: ```ts // inputString can be untrusted input const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`; // Safe if the text query below is completely trusted content const query = Prisma.sql`SELECT id, name FROM "User" WHERE name = ${inputString}`; const result = await prisma.$queryRaw(query); console.log(result); ``` In this example which is safe ✅ from SQL Injection, the `sql` helper method is used to build the query text including a parameter marker for the input value. Each variable is represented by a marker symbol (`?` for MySQL, `$1`, `$2`, and so on for PostgreSQL). Note that the examples just show PostgreSQL queries. ```ts // Version for Typescript const query: any; // Version for Javascript const query; // Safe if the text query below is completely trusted content query = Prisma.sql`SELECT id, name FROM "User" WHERE name = $1`; // inputString can be untrusted input const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`; query.values = [inputString]; const result = await prisma.$queryRaw(query); console.log(result); ``` > **Note**: PostgreSQL variables are represented by `$1`, etc ##### Building raw queries elsewhere or in stages If you want to build your raw queries somewhere other than where the query is executed, the ideal way to do this is to create an `Sql` object from the segments of your query and pass it the parameter value. In the following example we have two variables to parameterize. The example is safe ✅ from SQL Injection as long as the query strings being passed to `Prisma.sql` only contain trusted content: ```ts // Example is safe if the text query below is completely trusted content const query1 = `SELECT id, name FROM "User" WHERE name = `; // The first parameter would be inserted after this string const query2 = ` OR name = `; // The second parameter would be inserted after this string const inputString1 = "Fred"; const inputString2 = `'Sarah' UNION SELECT id, title FROM "Post"`; const query = Prisma.sql([query1, query2, ""], inputString1, inputString2); const result = await prisma.$queryRaw(query); console.log(result); ``` > Note: Notice that the string array being passed as the first parameter `Prisma.sql` needs to have an empty string at the end as the `sql` function expects one more query segment than the number of parameters. If you want to build your raw queries into one large string, this is still possible but requires some care as it is uses the potentially dangerous `Prisma.raw` method. You also need to build your query using the correct parameter markers for your database as Prisma won't be able to provide markers for the relevant database as it usually is. The following example is safe ✅ from SQL Injection as long as the query strings being passed to `Prisma.raw` only contain trusted content: ```ts // Version for Typescript const query: any; // Version for Javascript const query; // Example is safe if the text query below is completely trusted content const query1 = `SELECT id, name FROM "User" `; const query2 = `WHERE name = $1 `; query = Prisma.raw(`${query1}${query2}`); // inputString can be untrusted input const inputString = `'Sarah' UNION SELECT id, title FROM "Post"`; query.values = [inputString]; const result = await prisma.$queryRaw(query); console.log(result); ``` ### In `$queryRawUnsafe` and `$executeRawUnsafe` #### Using `$queryRawUnsafe` and `$executeRawUnsafe` unsafely If you cannot use tagged templates, you can instead use [`$queryRawUnsafe`](/orm/prisma-client/using-raw-sql/raw-queries#queryrawunsafe) or [`$executeRawUnsafe`](/orm/prisma-client/using-raw-sql/raw-queries#executerawunsafe). However, **be aware that these functions significantly increase the risk of SQL injection vulnerabilities in your code**. The following example concatenates `query` and `inputString`. Prisma Client ❌ **cannot** escape `inputString` in this example, which makes it vulnerable to SQL injection: ```ts const inputString = '"Sarah" UNION SELECT id, title, content FROM Post'; // SQL Injection const query = "SELECT id, name, email FROM User WHERE name = " + inputString; const result = await prisma.$queryRawUnsafe(query); console.log(result); ``` #### Parameterized queries As an alternative to tagged templates, `$queryRawUnsafe` supports standard parameterized queries where each variable is represented by a symbol (`?` for MySQL, `$1`, `$2`, and so on for PostgreSQL). Note that the examples just show PostgreSQL queries. The following example is safe ✅ from SQL Injection: ```ts const userName = "Sarah"; const email = "sarah@prisma.io"; const result = await prisma.$queryRawUnsafe( "SELECT * FROM User WHERE (name = $1 OR email = $2)", userName, email ); ``` > **Note**: PostgreSQL variables are represented by `$1` and `$2` As with tagged templates, Prisma Client escapes all variables when they are provided in this way. > **Note**: You cannot pass a table or column name as a variable into a parameterized query. For example, you cannot `SELECT ?` and pass in `*` or `id, name` based on some condition. ##### Parameterized PostgreSQL `ILIKE` query When you use `ILIKE`, the `%` wildcard character(s) should be included in the variable itself, not the query (`string`). This example is safe ✅ from SQL Injection. ```ts const userName = "Sarah"; const emailFragment = "prisma.io"; const result = await prisma.$queryRawUnsafe( 'SELECT * FROM "User" WHERE (name = $1 OR email ILIKE $2)', userName, `%${emailFragment}` ); ``` > **Note**: Using `%$2` as an argument would not work ## Raw queries with MongoDB For MongoDB in versions `3.9.0` and later, Prisma Client exposes three methods that allow you to send raw queries. You can use: - `$runCommandRaw` to run a command against the database - `.findRaw` to find zero or more documents that match the filter. - `.aggregateRaw` to perform aggregation operations on a collection. ### `$runCommandRaw()` `$runCommandRaw()` runs a raw MongoDB command against the database. As input, it accepts all [MongoDB database commands](https://www.mongodb.com/docs/manual/reference/command/), with the following exceptions: - `find` (use [`findRaw()`](#findraw) instead) - `aggregate` (use [`aggregateRaw()`](#aggregateraw) instead) When you use `$runCommandRaw()` to run a MongoDB database command, note the following: - The object that you pass when you invoke `$runCommandRaw()` must follow the syntax of the MongoDB database command. - You must connect to the database with an appropriate role for the MongoDB database command. In the following example, a query inserts two records with the same `_id`. This bypasses normal document validation. ```ts no-lines prisma.$runCommandRaw({ insert: "Pets", bypassDocumentValidation: true, documents: [ { _id: 1, name: "Felinecitas", type: "Cat", breed: "Russian Blue", age: 12, }, { _id: 1, name: "Nao Nao", type: "Dog", breed: "Chow Chow", age: 2, }, ], }); ``` :::warning Do not use `$runCommandRaw()` for queries which contain the `"find"` or `"aggregate"` commands, because you might be unable to fetch all data. This is because MongoDB returns a [cursor](https://www.mongodb.com/docs/manual/tutorial/iterate-a-cursor/) that is attached to your MongoDB session, and you might not hit the same MongoDB session every time. For these queries, you should use the specialised [`findRaw()`](#findraw) and [`aggregateRaw()`](#aggregateraw) methods instead. ::: #### Return type `$runCommandRaw()` returns a `JSON` object whose shape depends on the inputs. #### Signature ```ts no-lines $runCommandRaw(command: InputJsonObject): PrismaPromise; ``` ### `findRaw()` `.findRaw()` returns actual database records. It will find zero or more documents that match the filter on the `User` collection: ```ts no-lines const result = await prisma.user.findRaw({ filter: { age: { $gt: 25 } }, options: { projection: { _id: false } }, }); ``` #### Return type `.findRaw()` returns a `JSON` object whose shape depends on the inputs. #### Signature ```ts no-lines .findRaw(args?: {filter?: InputJsonObject, options?: InputJsonObject}): PrismaPromise; ``` - `filter`: The query predicate filter. If unspecified, then all documents in the collection will match the [predicate](https://www.mongodb.com/docs/manual/reference/operator/query). - `options`: Additional options to pass to the [`find` command](https://www.mongodb.com/docs/manual/reference/command/find/#command-fields). ### `aggregateRaw()` `.aggregateRaw()` returns aggregated database records. It will perform aggregation operations on the `User` collection: ```ts no-lines const result = await prisma.user.aggregateRaw({ pipeline: [ { $match: { status: "registered" } }, { $group: { _id: "$country", total: { $sum: 1 } } }, ], }); ``` #### Return type `.aggregateRaw()` returns a `JSON` object whose shape depends on the inputs. #### Signature ```ts no-lines .aggregateRaw(args?: {pipeline?: InputJsonObject[], options?: InputJsonObject}): PrismaPromise; ``` - `pipeline`: An array of aggregation stages to process and transform the document stream via the [aggregation pipeline](https://www.mongodb.com/docs/manual/reference/operator/aggregation-pipeline). - `options`: Additional options to pass to the [`aggregate` command](https://www.mongodb.com/docs/manual/reference/command/aggregate/#command-fields). #### Caveats When working with custom objects like `ObjectId` or `Date,` you will have to pass them according to the [MongoDB extended JSON Spec](https://www.mongodb.com/docs/manual/reference/mongodb-extended-json/#type-representations). Example: ```ts no-lines const result = await prisma.user.aggregateRaw({ pipeline: [ { $match: { _id: { $oid: id } } } // ^ notice the $oid convention here ], }); ``` --- # SafeQL & Prisma Client URL: https://www.prisma.io/docs/orm/prisma-client/using-raw-sql/safeql ## Overview This page explains how to improve the experience of writing raw SQL in Prisma ORM. It uses [Prisma Client extensions](/orm/prisma-client/client-extensions) and [SafeQL](https://safeql.dev) to create custom, type-safe Prisma Client queries which abstract custom SQL that your app might need (using `$queryRaw`). The example will be using [PostGIS](https://postgis.net/) and PostgreSQL, but is applicable to any raw SQL queries that you might need in your application. :::note This page builds on the [legacy raw query methods](/orm/prisma-client/using-raw-sql/raw-queries) available in Prisma Client. While many use cases for raw SQL in Prisma Client are covered by [TypedSQL](/orm/prisma-client/using-raw-sql/typedsql), using these legacy methods is still the recommended approach for working with `Unsupported` fields. ::: ## What is SafeQL? [SafeQL](https://safeql.dev/) allows for advanced linting and type safety within raw SQL queries. After setup, SafeQL works with Prisma Client `$queryRaw` and `$executeRaw` to provide type safety when raw queries are required. SafeQL runs as an [ESLint](https://eslint.org/) plugin and is configured using ESLint rules. This guide doesn't cover setting up ESLint and we will assume that you already having it running in your project. ## Prerequisites To follow along, you will be expected to have: - A [PostgreSQL](https://www.postgresql.org/) database with PostGIS installed - Prisma ORM set up in your project - ESLint set up in your project ## Geographic data support in Prisma ORM At the time of writing, Prisma ORM does not support working with geographic data, specifically using [PostGIS](https://github.com/prisma/prisma/issues/2789). A model that has geographic data columns will be stored using the [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) data type. Fields with `Unsupported` types are present in the generated Prisma Client and will be typed as `any`. A model with a required `Unsupported` type does not expose write operations such as `create`, and `update`. Prisma Client supports write operations on models with a required `Unsupported` field using `$queryRaw` and `$executeRaw`. You can use Prisma Client extensions and SafeQL to improve the type-safety when working with geographical data in raw queries. ## 1. Set up Prisma ORM for use with PostGIS If you haven't already, enable the `postgresqlExtensions` Preview feature and add the `postgis` PostgreSQL extension in your Prisma schema: ```prisma generator client { provider = "prisma-client-js" //add-next-line previewFeatures = ["postgresqlExtensions"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") //add-next-line extensions = [postgis] } ``` If you are not using a hosted database provider, you will likely need to install the `postgis` extension. Refer to [PostGIS's docs](http://postgis.net/documentation/getting_started/#installing-postgis) to learn more about how to get started with PostGIS. If you're using Docker Compose, you can use the following snippet to set up a PostgreSQL database that has PostGIS installed: ```yaml version: '3.6' services: pgDB: image: postgis/postgis:13-3.1-alpine restart: always ports: - '5432:5432' volumes: - db_data:/var/lib/postgresql/data environment: POSTGRES_PASSWORD: password POSTGRES_DB: geoexample volumes: db_data: ``` Next, create a migration and execute a migration to enable the extension: ```terminal npx prisma migrate dev --name add-postgis ``` For reference, the output of the migration file should look like the following: ```sql file=migrations/TIMESTAMP_add_postgis/migration.sql -- CreateExtension CREATE EXTENSION IF NOT EXISTS "postgis"; ``` You can double-check that the migration has been applied by running `prisma migrate status`. ## 2. Create a new model that uses a geographic data column Add a new model with a column with a `geography` data type once the migration is applied. For this guide, we'll use a model called `PointOfInterest`. ```prisma model PointOfInterest { id Int @id @default(autoincrement()) name String location Unsupported("geography(Point, 4326)") } ``` You'll notice that the `location` field uses an [`Unsupported`](/orm/reference/prisma-schema-reference#unsupported) type. This means that we lose a lot of the benefits of Prisma ORM when working with `PointOfInterest`. We'll be using [SafeQL](https://safeql.dev/) to fix this. Like before, create and execute a migration using the `prisma migrate dev` command to create the `PointOfInterest` table in your database: ```terminal npx prisma migrate dev --name add-poi ``` For reference, here is the output of the SQL migration file generated by Prisma Migrate: ```sql file=migrations/TIMESTAMP_add_poi/migration.sql -- CreateTable CREATE TABLE "PointOfInterest" ( "id" SERIAL NOT NULL, "name" TEXT NOT NULL, "location" geography(Point, 4326) NOT NULL, CONSTRAINT "PointOfInterest_pkey" PRIMARY KEY ("id") ); ``` ## 3. Integrate SafeQL SafeQL is easily integrated with Prisma ORM in order to lint `$queryRaw` and `$executeRaw` Prisma operations. You can reference [SafeQL's integration guide](https://safeql.dev/compatibility/prisma.html) or follow the steps below. ### 3.1. Install the `@ts-safeql/eslint-plugin` npm package ```terminal npm install -D @ts-safeql/eslint-plugin libpg-query ``` This ESLint plugin is what will allow for queries to be linted. ### 3.2. Add `@ts-safeql/eslint-plugin` to your ESLint plugins Next, add `@ts-safeql/eslint-plugin` to your list of ESLint plugins. In our example we are using an `.eslintrc.js` file, but this can be applied to any way that you [configure ESLint](https://eslint.org/docs/latest/use/configure/). ```js file=.eslintrc.js highlight=3 /** @type {import('eslint').Linter.Config} */ module.exports = { "plugins": [..., "@ts-safeql/eslint-plugin"], ... } ``` ### 3.3 Add `@ts-safeql/check-sql` rules Now, setup the rules that will enable SafeQL to mark invalid SQL queries as ESLint errors. ```js file=.eslintrc.js highlight=4-22;add /** @type {import('eslint').Linter.Config} */ module.exports = { plugins: [..., '@ts-safeql/eslint-plugin'], //add-start rules: { '@ts-safeql/check-sql': [ 'error', { connections: [ { // The migrations path: migrationsDir: './prisma/migrations', targets: [ // This makes `prisma.$queryRaw` and `prisma.$executeRaw` commands linted { tag: 'prisma.+($queryRaw|$executeRaw)', transform: '{type}[]' }, ], }, ], }, ], }, } //add-end ``` > **Note**: If your `PrismaClient` instance is called something different than `prisma`, you need to adjust the value for `tag` accordingly. For example, if it is called `db`, the value for `tag` should be `'db.+($queryRaw|$executeRaw)'`. ### 3.4. Connect to your database Finally, set up a `connectionUrl` for SafeQL so that it can introspect your database and retrieve the table and column names you use in your schema. SafeQL then uses this information for linting and highlighting problems in your raw SQL statements. Our example relies on the [`dotenv`](https://github.com/motdotla/dotenv) package to get the same connection string that is used by Prisma ORM. We recommend this in order to keep your database URL out of version control. If you haven't installed `dotenv` yet, you can install it as follows: ```terminal npm install dotenv ``` Then update your ESLint config as follows: ```js file=.eslintrc.js highlight=1,6-9,16;add //add-next-line require('dotenv').config() /** @type {import('eslint').Linter.Config} */ module.exports = { plugins: ['@ts-safeql/eslint-plugin'], //add-start // exclude `parserOptions` if you are not using TypeScript parserOptions: { project: './tsconfig.json', }, //add-end rules: { '@ts-safeql/check-sql': [ 'error', { connections: [ { //add-next-line connectionUrl: process.env.DATABASE_URL, // The migrations path: migrationsDir: './prisma/migrations', targets: [ // what you would like SafeQL to lint. This makes `prisma.$queryRaw` and `prisma.$executeRaw` // commands linted { tag: 'prisma.+($queryRaw|$executeRaw)', transform: '{type}[]' }, ], }, ], }, ], }, } ``` SafeQL is now fully configured to help you write better raw SQL using Prisma Client. ## 4. Creating extensions to make raw SQL queries type-safe In this section, we'll create two [`model`](/orm/prisma-client/client-extensions/model) extensions with custom queries to be able to work conveniently with the `PointOfInterest` model: 1. A `create` query that allows us to create new `PointOfInterest` records in the database 1. A `findClosestPoints` query that returns the `PointOfInterest` records that are closest to a given coordinate ### 4.1. Adding an extension to create `PointOfInterest` records The `PointOfInterest` model in the Prisma schema uses an `Unsupported` type. As a consequence, the generated `PointOfInterest` type in Prisma Client can't be used to carry values for latitude and longitude. We will resolve this by defining two custom types that better represent our model in TypeScript: ```ts type MyPoint = { latitude: number longitude: number } type MyPointOfInterest = { name: string location: MyPoint } ``` Next, you can add a `create` query to the `pointOfInterest` property of your Prisma Client: ```ts highlight=19;normal const prisma = new PrismaClient().$extends({ model: { pointOfInterest: { async create(data: { name: string latitude: number longitude: number }) { // Create an object using the custom types from above const poi: MyPointOfInterest = { name: data.name, location: { latitude: data.latitude, longitude: data.longitude, }, } // Insert the object into the database const point = `POINT(${poi.location.longitude} ${poi.location.latitude})` await prisma.$queryRaw` INSERT INTO "PointOfInterest" (name, location) VALUES (${poi.name}, ST_GeomFromText(${point}, 4326)); ` // Return the object return poi }, }, }, }) ``` Notice that the SQL in the line that's highlighted in the code snippet gets checked by SafeQL! For example, if you change the name of the table from `"PointOfInterest"` to `"PointOfInterest2"`, the following error appears: ``` error Invalid Query: relation "PointOfInterest2" does not exist @ts-safeql/check-sql ``` This also works with the column names `name` and `location`. You can now create new `PointOfInterest` records in your code as follows: ```ts const poi = await prisma.pointOfInterest.create({ name: 'Berlin', latitude: 52.52, longitude: 13.405, }) ``` ### 4.2. Adding an extension to query for closest to `PointOfInterest` records Now let's make a Prisma Client extension in order to query this model. We will be making an extension that finds the closest points of interest to a given longitude and latitude. ```ts const prisma = new PrismaClient().$extends({ model: { pointOfInterest: { async create(data: { name: string latitude: number longitude: number }) { // ... same code as before }, async findClosestPoints(latitude: number, longitude: number) { // Query for clostest points of interests const result = await prisma.$queryRaw< { id: number | null name: string | null st_x: number | null st_y: number | null }[] >`SELECT id, name, ST_X(location::geometry), ST_Y(location::geometry) FROM "PointOfInterest" ORDER BY ST_DistanceSphere(location::geometry, ST_MakePoint(${longitude}, ${latitude})) DESC` // Transform to our custom type const pois: MyPointOfInterest[] = result.map((data) => { return { name: data.name, location: { latitude: data.st_x || 0, longitude: data.st_y || 0, }, } }) // Return data return pois }, }, }, }) ``` Now, you can use our Prisma Client as normal to find close points of interest to a given longitude and latitude using the custom method created on the `PointOfInterest` model. ```ts const closestPointOfInterest = await prisma.pointOfInterest.findClosestPoints( 53.5488, 9.9872 ) ``` Similar to before, we again have the benefit of SafeQL to add extra type safety to our raw queries. For example, if we removed the cast to `geometry` for `location` by changing `location::geometry` to just `location`, we would get linting errors in the `ST_X`, `ST_Y` or `ST_DistanceSphere` functions respectively. ```terminal error Invalid Query: function st_distancesphere(geography, geometry) does not exist @ts-safeql/check-sql ``` ## Conclusion While you may sometimes need to drop down to raw SQL when using Prisma ORM, you can use various techniques to make the experience of writing raw SQL queries with Prisma ORM better. In this article, you have used SafeQL and Prisma Client extensions to create custom, type-safe Prisma Client queries to abstract PostGIS operations which are currently not natively supported in Prisma ORM. --- # Write your own SQL URL: https://www.prisma.io/docs/orm/prisma-client/using-raw-sql/index While the Prisma Client API aims to make all your database queries intuitive, type-safe, and convenient, there may still be situations where raw SQL is the best tool for the job. This can happen for various reasons, such as the need to optimize the performance of a specific query or because your data requirements can't be fully expressed by Prisma Client's query API. In most cases, [TypedSQL](#writing-type-safe-queries-with-prisma-client-and-typedsql) allows you to express your query in SQL while still benefiting from Prisma Client's excellent user experience. However, since TypedSQL is statically typed, it may not handle certain scenarios, such as dynamically generated `WHERE` clauses. In these cases, you will need to use [`$queryRaw`](/orm/prisma-client/using-raw-sql/raw-queries#queryraw) or [`$executeRaw`](/orm/prisma-client/using-raw-sql/raw-queries#executeraw), or their unsafe counterparts. ## Writing type-safe queries with Prisma Client and TypedSQL :::info TypedSQL is available in Prisma ORM 5.19.0 and later. For raw database access in previous versions, see [our raw queries documentation](/orm/prisma-client/using-raw-sql/raw-queries). ::: ### What is TypedSQL? TypedSQL is a new feature of Prisma ORM that allows you to write your queries in `.sql` files while still enjoying the great developer experience of Prisma Client. You can write the code you're comfortable with and benefit from fully-typed inputs and outputs. With TypedSQL, you can: 1. Write complex SQL queries using familiar syntax 2. Benefit from full IDE support and syntax highlighting for SQL 3. Import your SQL queries as fully typed functions in your TypeScript code 4. Maintain the flexibility of raw SQL with the safety of Prisma's type system TypedSQL is particularly useful for: - Complex reporting queries that are difficult to express using Prisma's query API - Performance-critical operations that require fine-tuned SQL - Leveraging database-specific features not yet supported in Prisma's API By using TypedSQL, you can write efficient, type-safe database queries without sacrificing the power and flexibility of raw SQL. This feature allows you to seamlessly integrate custom SQL queries into your Prisma-powered applications, ensuring type safety and improving developer productivity. For a detailed guide on how to get started with TypedSQL, including setup instructions and usage examples, please refer to our [TypedSQL documentation](/orm/prisma-client/using-raw-sql/typedsql). ## Raw queries Prior to version 5.19.0, Prisma Client only supported raw SQL queries that were not type-safe and required manual mapping of the query result to the desired type. While not as ergonomic as [TypedSQL](#writing-type-safe-queries-with-prisma-client-and-typedsql), these queries are still supported and are useful when TypedSQL queries are not possible either due to features not yet supported in TypedSQL or when the query is dynamically generated. ### Alternative approaches to raw SQL queries in relational databases Prisma ORM supports four methods to execute raw SQL queries in relational databases: - [`$queryRaw`](/orm/prisma-client/using-raw-sql/raw-queries#queryraw) - [`$executeRaw`](/orm/prisma-client/using-raw-sql/raw-queries#executeraw) - [`$queryRawUnsafe`](/orm/prisma-client/using-raw-sql/raw-queries#queryrawunsafe) - [`$executeRawUnsafe`](/orm/prisma-client/using-raw-sql/raw-queries#executerawunsafe) These commands are similar to using TypedSQL, but they are not type-safe and are written as strings in your code rather than in dedicated `.sql` files. ### Alternative approaches to raw queries in document databases For MongoDB, Prisma ORM supports three methods to execute raw queries: - [`$runCommandRaw`](/orm/prisma-client/using-raw-sql/raw-queries#runcommandraw) - [`.findRaw`](/orm/prisma-client/using-raw-sql/raw-queries#findraw) - [`.aggregateRaw`](/orm/prisma-client/using-raw-sql/raw-queries#aggregateraw) These methods allow you to execute raw MongoDB commands and queries, providing flexibility when you need to use MongoDB-specific features or optimizations. `$runCommandRaw` is used to execute database commands, `.findRaw` is used to find documents that match a filter, and `.aggregateRaw` is used for aggregation operations. All three methods are available from Prisma version 3.9.0 and later. Similar to raw queries in relational databases, these methods are not type-safe and require manual handling of the query results. --- # Composite types URL: https://www.prisma.io/docs/orm/prisma-client/special-fields-and-types/composite-types Composite types are only available with MongoDB. [Composite types](/orm/prisma-schema/data-model/models#defining-composite-types), known as [embedded documents](https://www.mongodb.com/docs/manual/data-modeling/#embedded-data) in MongoDB, allow you to embed records within other records. We made composite types [Generally Available](/orm/more/releases#generally-available-ga) in v3.12.0. They were previously available in [Preview](/orm/reference/preview-features) from v3.10.0. This page explains how to: - [find](#finding-records-that-contain-composite-types-with-find-and-findmany) records that contain composite types using `findFirst` and `findMany` - [create](#creating-records-with-composite-types-using-create-and-createmany) new records with composite types using `create` and `createMany` - [update](#changing-composite-types-within-update-and-updatemany) composite types within existing records using `update` and `updateMany` - [delete](#deleting-records-that-contain-composite-types-with-delete-and-deletemany) records with composite types using `delete` and `deleteMany` ## Example schema We’ll use this schema for the examples that follow: ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" } datasource db { provider = "mongodb" url = env("DATABASE_URL") } model Product { id String @id @default(auto()) @map("_id") @db.ObjectId name String @unique price Float colors Color[] sizes Size[] photos Photo[] orders Order[] } model Order { id String @id @default(auto()) @map("_id") @db.ObjectId product Product @relation(fields: [productId], references: [id]) color Color size Size shippingAddress Address billingAddress Address? productId String @db.ObjectId } enum Color { Red Green Blue } enum Size { Small Medium Large XLarge } type Photo { height Int @default(200) width Int @default(100) url String } type Address { street String city String zip String } ``` In this schema, the `Product` model has a `Photo[]` composite type, and the `Order` model has two composite `Address` types. The `shippingAddress` is required, but the `billingAddress` is optional. ## Considerations when using composite types There are currently some limitations when using composite types in Prisma Client: - [`findUnique()`](/orm/reference/prisma-client-reference#findunique) can't filter on composite types - [`aggregate`](/orm/prisma-client/queries/aggregation-grouping-summarizing#aggregate), [`groupBy()`](/orm/prisma-client/queries/aggregation-grouping-summarizing#group-by), [`count`](/orm/prisma-client/queries/aggregation-grouping-summarizing#count) don’t support composite operations ## Default values for required fields on composite types From version 4.0.0, if you carry out a database read on a composite type when all of the following conditions are true, then Prisma Client inserts the default value into the result. Conditions: - A field on the composite type is [required](/orm/prisma-schema/data-model/models#optional-and-mandatory-fields), and - this field has a [default value](/orm/prisma-schema/data-model/models#defining-a-default-value), and - this field is not present in the returned document or documents. Note: - This is the same behavior as with [model fields](/orm/reference/prisma-schema-reference#model-field-scalar-types). - On read operations, Prisma Client inserts the default value into the result, but does not insert the default value into the database. In our example schema, suppose that you add a required field to `photo`. This field, `bitDepth`, has a default value: ```prisma file=schema.prisma highlight=4;add ... type Photo { ... //add-next-line bitDepth Int @default(8) } ... ``` Suppose that you then run `npx prisma db push` to [update your database](/orm/reference/prisma-cli-reference#db-push) and regenerate your Prisma Client with `npx prisma generate`. Then, you run the following application code: ```ts console.dir(await prisma.product.findMany({}), { depth: Infinity }) ``` The `bitDepth` field has no content because you have only just added this field, so the query returns the default value of `8`. ** Earlier versions ** Before version 4.0.0, Prisma ORM threw a P2032 error as follows: ``` Error converting field "bitDepth" of expected non-nullable type "int", found incompatible value of "null". ``` ## Finding records that contain composite types with `find` and `findMany` Records can be filtered by a composite type within the `where` operation. The following section describes the operations available for filtering by a single type or multiple types, and gives examples of each. ### Filtering for one composite type Use the `is`, `equals`, `isNot` and `isSet` operations to change a single composite type: - `is`: Filter results by matching composite types. Requires one or more fields to be present _(e.g. Filter orders by the street name on the shipping address)_ - `equals`: Filter results by matching composite types. Requires all fields to be present. _(e.g. Filter orders by the full shipping address)_ - `isNot`: Filter results by non-matching composite types - `isSet` : Filter optional fields to include only results that have been set (either set to a value, or explicitly set to `null`). Setting this filter to `true` will exclude `undefined` results that are not set at all. For example, use `is` to filter for orders with a street name of `'555 Candy Cane Lane'`: ```ts const orders = await prisma.order.findMany({ where: { shippingAddress: { is: { street: '555 Candy Cane Lane', }, }, }, }) ``` Use `equals` to filter for orders which match on all fields in the shipping address: ```ts const orders = await prisma.order.findMany({ where: { shippingAddress: { equals: { street: '555 Candy Cane Lane', city: 'Wonderland', zip: '52337', }, }, }, }) ``` You can also use a shorthand notation for this query, where you leave out the `equals`: ```ts const orders = await prisma.order.findMany({ where: { shippingAddress: { street: '555 Candy Cane Lane', city: 'Wonderland', zip: '52337', }, }, }) ``` Use `isNot` to filter for orders that do not have a `zip` code of `'52337'`: ```ts const orders = await prisma.order.findMany({ where: { shippingAddress: { isNot: { zip: '52337', }, }, }, }) ``` Use `isSet` to filter for orders where the optional `billingAddress` has been set (either to a value or to `null`): ```ts const orders = await prisma.order.findMany({ where: { billingAddress: { isSet: true, }, }, }) ``` ### Filtering for many composite types Use the `equals`, `isEmpty`, `every`, `some` and `none` operations to filter for multiple composite types: - `equals`: Checks exact equality of the list - `isEmpty`: Checks if the list is empty - `every`: Every item in the list must match the condition - `some`: One or more of the items in the list must match the condition - `none`: None of the items in the list can match the condition - `isSet` : Filter optional fields to include only results that have been set (either set to a value, or explicitly set to `null`). Setting this filter to `true` will exclude `undefined` results that are not set at all. For example, you can use `equals` to find products with a specific list of photos (all `url`, `height` and `width` fields must match): ```ts const product = prisma.product.findMany({ where: { photos: { equals: [ { url: '1.jpg', height: 200, width: 100, }, { url: '2.jpg', height: 200, width: 100, }, ], }, }, }) ``` You can also use a shorthand notation for this query, where you leave out the `equals` and specify just the fields that you want to filter for: ```ts const product = prisma.product.findMany({ where: { photos: [ { url: '1.jpg', height: 200, width: 100, }, { url: '2.jpg', height: 200, width: 100, }, ], }, }) ``` Use `isEmpty` to filter for products with no photos: ```ts const product = prisma.product.findMany({ where: { photos: { isEmpty: true, }, }, }) ``` Use `some` to filter for products where one or more photos has a `url` of `"2.jpg"`: ```ts const product = prisma.product.findFirst({ where: { photos: { some: { url: '2.jpg', }, }, }, }) ``` Use `none` to filter for products where no photos have a `url` of `"2.jpg"`: ```ts const product = prisma.product.findFirst({ where: { photos: { none: { url: '2.jpg', }, }, }, }) ``` ## Creating records with composite types using `create` and `createMany` When you create a record with a composite type that has a unique restraint, note that MongoDB does not enforce unique values inside a record. [Learn more](#duplicate-values-in-unique-fields-of-composite-types). Composite types can be created within a `create` or `createMany` method using the `set` operation. For example, you can use `set` within `create` to create an `Address` composite type inside an `Order`: ```ts const order = await prisma.order.create({ data: { // Normal relation product: { connect: { id: 'some-object-id' } }, color: 'Red', size: 'Large', // Composite type shippingAddress: { set: { street: '1084 Candycane Lane', city: 'Silverlake', zip: '84323', }, }, }, }) ``` You can also use a shorthand notation where you leave out the `set` and specify just the fields that you want to create: ```ts const order = await prisma.order.create({ data: { // Normal relation product: { connect: { id: 'some-object-id' } }, color: 'Red', size: 'Large', // Composite type shippingAddress: { street: '1084 Candycane Lane', city: 'Silverlake', zip: '84323', }, }, }) ``` For an optional type, like the `billingAddress`, you can also set the value to `null`: ```ts const order = await prisma.order.create({ data: { // Normal relation product: { connect: { id: 'some-object-id' } }, color: 'Red', size: 'Large', // Composite type shippingAddress: { street: '1084 Candycane Lane', city: 'Silverlake', zip: '84323', }, // Embedded optional type, set to null billingAddress: { set: null, }, }, }) ``` To model the case where an `product` contains a list of multiple `photos`, you can `set` multiple composite types at once: ```ts const product = await prisma.product.create({ data: { name: 'Forest Runners', price: 59.99, colors: ['Red', 'Green'], sizes: ['Small', 'Medium', 'Large'], // New composite type photos: { set: [ { height: 100, width: 200, url: '1.jpg' }, { height: 100, width: 200, url: '2.jpg' }, ], }, }, }) ``` You can also use a shorthand notation where you leave out the `set` and specify just the fields that you want to create: ```ts const product = await prisma.product.create({ data: { name: 'Forest Runners', price: 59.99, // Scalar lists that we already support colors: ['Red', 'Green'], sizes: ['Small', 'Medium', 'Large'], // New composite type photos: [ { height: 100, width: 200, url: '1.jpg' }, { height: 100, width: 200, url: '2.jpg' }, ], }, }) ``` These operations also work within the `createMany` method. For example, you can create multiple `product`s which each contain a list of `photos`: ```ts const product = await prisma.product.createMany({ data: [ { name: 'Forest Runners', price: 59.99, colors: ['Red', 'Green'], sizes: ['Small', 'Medium', 'Large'], photos: [ { height: 100, width: 200, url: '1.jpg' }, { height: 100, width: 200, url: '2.jpg' }, ], }, { name: 'Alpine Blazers', price: 85.99, colors: ['Blue', 'Red'], sizes: ['Large', 'XLarge'], photos: [ { height: 100, width: 200, url: '1.jpg' }, { height: 150, width: 200, url: '4.jpg' }, { height: 200, width: 200, url: '5.jpg' }, ], }, ], }) ``` ## Changing composite types within `update` and `updateMany` When you update a record with a composite type that has a unique restraint, note that MongoDB does not enforce unique values inside a record. [Learn more](#duplicate-values-in-unique-fields-of-composite-types). Composite types can be set, updated or removed within an `update` or `updateMany` method. The following section describes the operations available for updating a single type or multiple types at once, and gives examples of each. ### Changing a single composite type Use the `set`, `unset` `update` and `upsert` operations to change a single composite type: - Use `set` to set a composite type, overriding any existing value - Use `unset` to unset a composite type. Unlike `set: null`, `unset` removes the field entirely - Use `update` to update a composite type - Use `upsert` to `update` an existing composite type if it exists, and otherwise `set` the composite type For example, use `update` to update a required `shippingAddress` with an `Address` composite type inside an `Order`: ```ts const order = await prisma.order.update({ where: { id: 'some-object-id', }, data: { shippingAddress: { // Update just the zip field update: { zip: '41232', }, }, }, }) ``` For an optional embedded type, like the `billingAddress`, use `upsert` to create a new record if it does not exist, and update the record if it does: ```ts const order = await prisma.order.update({ where: { id: 'some-object-id', }, data: { billingAddress: { // Create the address if it doesn't exist, // otherwise update it upsert: { set: { street: '1084 Candycane Lane', city: 'Silverlake', zip: '84323', }, update: { zip: '84323', }, }, }, }, }) ``` You can also use the `unset` operation to remove an optional embedded type. The following example uses `unset` to remove the `billingAddress` from an `Order`: ```ts const order = await prisma.order.update({ where: { id: 'some-object-id', }, data: { billingAddress: { // Unset the billing address // Removes "billingAddress" field from order unset: true, }, }, }) ``` You can use [filters](/orm/prisma-client/special-fields-and-types/composite-types#finding-records-that-contain-composite-types-with-find-and-findmany) within `updateMany` to update all records that match a composite type. The following example uses the `is` filter to match the street name from a shipping address on a list of orders: ```ts const orders = await prisma.order.updateMany({ where: { shippingAddress: { is: { street: '555 Candy Cane Lane', }, }, }, data: { shippingAddress: { update: { street: '111 Candy Cane Drive', }, }, }, }) ``` ### Changing multiple composite types Use the `set`, `push`, `updateMany` and `deleteMany` operations to change a list of composite types: - `set`: Set an embedded list of composite types, overriding any existing list - `push`: Push values to the end of an embedded list of composite types - `updateMany`: Update many composite types at once - `deleteMany`: Delete many composite types at once For example, use `push` to add a new photo to the `photos` list: ```ts const product = prisma.product.update({ where: { id: '62de6d328a65d8fffdae2c18', }, data: { photos: { // Push a photo to the end of the photos list push: [{ height: 100, width: 200, url: '1.jpg' }], }, }, }) ``` Use `updateMany` to update photos with a `url` of `1.jpg` or `2.png`: ```ts const product = prisma.product.update({ where: { id: '62de6d328a65d8fffdae2c18', }, data: { photos: { updateMany: { where: { url: '1.jpg', }, data: { url: '2.png', }, }, }, }, }) ``` The following example uses `deleteMany` to delete all photos with a `height` of 100: ```ts const product = prisma.product.update({ where: { id: '62de6d328a65d8fffdae2c18', }, data: { photos: { deleteMany: { where: { height: 100, }, }, }, }, }) ``` ## Upserting composite types with `upsert` When you create or update the values in a composite type that has a unique restraint, note that MongoDB does not enforce unique values inside a record. [Learn more](#duplicate-values-in-unique-fields-of-composite-types). To create or update a composite type, use the `upsert` method. You can use the same composite operations as the `create` and `update` methods above. For example, use `upsert` to either create a new product or add a photo to an existing product: ```ts const product = await prisma.product.upsert({ where: { name: 'Forest Runners', }, create: { name: 'Forest Runners', price: 59.99, colors: ['Red', 'Green'], sizes: ['Small', 'Medium', 'Large'], photos: [ { height: 100, width: 200, url: '1.jpg' }, { height: 100, width: 200, url: '2.jpg' }, ], }, update: { photos: { push: { height: 300, width: 400, url: '3.jpg' }, }, }, }) ``` ## Deleting records that contain composite types with `delete` and `deleteMany` To remove records which embed a composite type, use the `delete` or `deleteMany` methods. This will also remove the embedded composite type. For example, use `deleteMany` to delete all products with a `size` of `"Small"`. This will also delete any embedded `photos`. ```ts const deleteProduct = await prisma.product.deleteMany({ where: { sizes: { equals: 'Small', }, }, }) ``` You can also use [filters](/orm/prisma-client/special-fields-and-types/composite-types#finding-records-that-contain-composite-types-with-find-and-findmany) to delete records that match a composite type. The example below uses the `some` filter to delete products that contain a certain photo: ```ts const product = await prisma.product.deleteMany({ where: { photos: { some: { url: '2.jpg', }, }, }, }) ``` ## Ordering composite types You can use the `orderBy` operation to sort results in ascending or descending order. For example, the following command finds all orders and orders them by the city name in the shipping address, in ascending order: ```ts const orders = await prisma.order.findMany({ orderBy: { shippingAddress: { city: 'asc', }, }, }) ``` ## Duplicate values in unique fields of composite types Be careful when you carry out any of the following operations on a record with a composite type that has a unique constraint. In this situation, MongoDB does not enforce unique values inside a record. - When you create the record - When you add data to the record - When you update data in the record If your schema has a composite type with a `@@unique` constraint, MongoDB prevents you from storing the same value for the constrained value in two or more of the records that contain this composite type. However, MongoDB does does not prevent you from storing multiple copies of the same field value in a single record. Note that you can [use Prisma ORM relations to work around this issue](#use-prisma-orm-relations-to-enforce-unique-values-in-a-record). For example, in the following schema, `MailBox` has a composite type, `addresses`, which has a `@@unique` constraint on the `email` field. ```prisma type Address { email String } model MailBox { name String addresses Address[] @@unique([addresses.email]) } ``` The following code creates a record with two identical values in `address`. MongoDB does not throw an error in this situation, and it stores `alice@prisma.io` in `addresses` twice. ```ts await prisma.MailBox.createMany({ data: [ { name: 'Alice', addresses: { set: [ { address: 'alice@prisma.io', // Not unique }, { address: 'alice@prisma.io', // Not unique }, ], }, }, ], }) ``` Note: MongoDB throws an error if you try to store the same value in two separate records. In our example above, if you try to store the email address `alice@prisma.io` for the user Alice and for the user Bob, MongoDB does not store the data and throws an error. ### Use Prisma ORM relations to enforce unique values in a record In the example above, MongoDB did not enforce the unique constraint on a nested address name. However, you can model your data differently to enforce unique values in a record. To do so, use Prisma ORM [relations](/orm/prisma-schema/data-model/relations) to turn the composite type into a collection. Set a relationship to this collection and place a unique constraint on the field that you want to be unique. In the following example, MongoDB enforces unique values in a record. There is a relation between `Mailbox` and the `Address` model. Also, the `name` field in the `Address` model has a unique constraint. ```prisma model Address { id String @id @default(auto()) @map("_id") @db.ObjectId name String mailbox Mailbox? @relation(fields: [mailboxId], references: [id]) mailboxId String? @db.ObjectId @@unique([name]) } model Mailbox { id String @id @default(auto()) @map("_id") @db.ObjectId name String addresses Address[] @relation } ``` ```ts await prisma.MailBox.create({ data: { name: 'Alice', addresses: { create: [ { name: 'alice@prisma.io' }, // Not unique { name: 'alice@prisma.io' }, // Not unique ], }, }, }) ``` If you run the above code, MongoDB enforces the unique constraint. It does not allow your application to add two addresses with the name `alice@prisma.io`. --- # Null and undefined URL: https://www.prisma.io/docs/orm/prisma-client/special-fields-and-types/null-and-undefined :::warning In Prisma ORM, if `undefined` is passed as a value, it is not included in the generated query. This behavior can lead to unexpected results and data loss. In order to prevent this, we strongly recommend updating to version 5.20.0 or later to take advantage of the new `strictUndefinedChecks` Preview feature, described below. For documentation on the current behavior (without the `strictUndefinedChecks` Preview feature) see [current behavior](#current-behavior). ::: ## Strict undefined checks (Preview feature) Prisma ORM 5.20.0 introduces a new Preview feature called `strictUndefinedChecks`. This feature changes how Prisma Client handles `undefined` values, offering better protection against accidental data loss or unintended query behavior. ### Enabling strict undefined checks To enable this feature, add the following to your Prisma schema: ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["strictUndefinedChecks"] } ``` ### Using strict undefined checks When this feature is enabled: 1. Explicitly setting a field to `undefined` in a query will cause a runtime error. 2. To skip a field in a query, use the new `Prisma.skip` symbol instead of `undefined`. Example usage: ```typescript // This will throw an error prisma.user.create({ data: { name: 'Alice', email: undefined // Error: Cannot explicitly use undefined here } }) // Use `Prisma.skip` (a symbol provided by Prisma) to omit a field prisma.user.create({ data: { name: 'Alice', email: Prisma.skip // This field will be omitted from the query } }) ``` This change helps prevent accidental deletions or updates, such as: ```typescript // Before: This would delete all users prisma.user.deleteMany({ where: { id: undefined } }) // After: This will throw an error Invalid \`prisma.user.deleteMany()\` invocation in /client/tests/functional/strictUndefinedChecks/test.ts:0:0 XX }) XX XX test('throws on undefined input field', async () => { → XX const result = prisma.user.deleteMany({ where: { id: undefined ~~~~~~~~~ } }) Invalid value for argument \`where\`: explicitly \`undefined\` values are not allowed." ``` ### Migration path To migrate existing code: ```typescript // Before let optionalEmail: string | undefined prisma.user.create({ data: { name: 'Alice', email: optionalEmail } }) // After prisma.user.create({ data: { name: 'Alice', // highlight-next-line email: optionalEmail ?? Prisma.skip } }) ``` ### `exactOptionalPropertyTypes` In addition to `strictUndefinedChecks`, we also recommend enabling the TypeScript compiler option `exactOptionalPropertyTypes`. This option enforces that optional properties must match exactly, which can help catch potential issues with `undefined` values in your code. While `strictUndefinedChecks` will raise runtime errors for invalid `undefined` usage, `exactOptionalPropertyTypes` will catch these issues during the build process. Learn more about `exactOptionalPropertyTypes` in the [TypeScript documentation](https://www.typescriptlang.org/tsconfig/#exactOptionalPropertyTypes). ### Feedback As always, we welcome your feedback on this feature. Please share your thoughts and suggestions in the [GitHub discussion for this Preview feature](https://github.com/prisma/prisma/discussions/25271). ## current behavior Prisma Client differentiates between `null` and `undefined`: - `null` is a **value** - `undefined` means **do nothing** :::info This is particularly important to account for in [a **Prisma ORM with GraphQL context**, where `null` and `undefined` are interchangeable](#null-and-undefined-in-a-graphql-resolver). ::: The data below represents a `User` table. This set of data will be used in all of the examples below: | id | name | email | | --- | ------- | ----------------- | | 1 | Nikolas | nikolas@gmail.com | | 2 | Martin | martin@gmail.com | | 3 | _empty_ | sabin@gmail.com | | 4 | Tyler | tyler@gmail.com | ### `null` and `undefined` in queries that affect _many_ records This section will cover how `undefined` and `null` values affect the behavior of queries that interact with or create multiple records in a database. #### Null Consider the following Prisma Client query which searches for all users whose `name` value matches the provided `null` value: ```ts const users = await prisma.user.findMany({ where: { name: null, }, }) ``` ```json [ { "id": 3, "name": null, "email": "sabin@gmail.com" } ] ``` Because `null` was provided as the filter for the `name` column, Prisma Client will generate a query that searches for all records in the `User` table whose `name` column is _empty_. #### Undefined Now consider the scenario where you run the same query with `undefined` as the filter value on the `name` column: ```ts const users = await prisma.user.findMany({ where: { name: undefined, }, }) ``` ```json [ { "id": 1, "name": "Nikolas", "email": "nikolas@gmail.com" }, { "id": 2, "name": "Martin", "email": "martin@gmail.com" }, { "id": 3, "name": null, "email": "sabin@gmail.com" }, { "id": 4, "name": "Tyler", "email": "tyler@gmail.com" } ] ``` Using `undefined` as a value in a filter essentially tells Prisma Client you have decided _not to define a filter_ for that column. An equivalent way to write the above query would be: ```ts const users = await prisma.user.findMany() ``` This query will select every row from the `User` table. **Note**: Using `undefined` as the value of any key in a Prisma Client query's parameter object will cause Prisma ORM to act as if that key was not provided at all. Although this section's examples focused on the `findMany` function, the same concepts apply to any function that can affect multiple records, such as `updateMany` and `deleteMany`. ### `null` and `undefined` in queries that affect _one_ record This section will cover how `undefined` and `null` values affect the behavior of queries that interact with or create a single record in a database. **Note**: `null` is not a valid filter value in a `findUnique()` query. The query behavior when using `null` and `undefined` in the filter criteria of a query that affects a single record is very similar to the behaviors described in the previous section. #### Null Consider the following query where `null` is used to filter the `name` column: ```ts const user = await prisma.user.findFirst({ where: { name: null, }, }) ``` ```json [ { "id": 3, "name": null, "email": "sabin@gmail.com" } ] ``` Because `null` was used as the filter on the `name` column, Prisma Client will generate a query that searches for the first record in the `User` table whose `name` value is _empty_. #### Undefined If `undefined` is used as the filter value on the `name` column instead, _the query will act as if no filter criteria was passed to that column at all_. Consider the query below: ```ts const user = await prisma.user.findFirst({ where: { name: undefined, }, }) ``` ```json [ { "id": 1, "name": "Nikolas", "email": "nikolas@gmail.com" } ] ``` In this scenario, the query will return the very first record in the database. Another way to represent the above query is: ```ts const user = await prisma.user.findFirst() ``` Although this section's examples focused on the `findFirst` function, the same concepts apply to any function that affects a single record. ### `null` and `undefined` in a GraphQL resolver For this example, consider a database based on the following Prisma schema: ```prisma model User { id Int @id @default(autoincrement()) email String @unique name String? } ``` In the following GraphQL mutation that updates a user, both `authorEmail` and `name` accept `null`. From a GraphQL perspective, this means that fields are **optional**: ```ts type Mutation { // Update author's email or name, or both - or neither! updateUser(id: Int!, authorEmail: String, authorName: String): User! } ``` However, if you pass `null` values for `authorEmail` or `authorName` on to Prisma Client, the following will happen: - If `args.authorEmail` is `null`, the query will **fail**. `email` does not accept `null`. - If `args.authorName` is `null`, Prisma Client changes the value of `name` to `null`. This is probably not how you want an update to work. ```ts updateUser: (parent, args, ctx: Context) => { return ctx.prisma.user.update({ where: { id: Number(args.id) }, data: { //highlight-start email: args.authorEmail, // email cannot be null name: args.authorName // name set to null - potentially unwanted behavior //highlight-end }, }) }, ``` Instead, set the value of `email` and `name` to `undefined` if the input value is `null`. Doing this is the same as not updating the field at all: ```ts updateUser: (parent, args, ctx: Context) => { return ctx.prisma.user.update({ where: { id: Number(args.id) }, data: { //highlight-start email: args.authorEmail != null ? args.authorEmail : undefined, // If null, do nothing name: args.authorName != null ? args.authorName : undefined // If null, do nothing //highlight-end }, }) }, ``` ### The effect of `null` and `undefined` on conditionals There are some caveats to filtering with conditionals which might produce unexpected results. When filtering with conditionals you might expect one result but receive another given how Prisma Client treats nullable values. The following table provides a high-level overview of how the different operators handle 0, 1 and `n` filters. | Operator | 0 filters | 1 filter | n filters | | -------- | ----------------- | ---------------------- | -------------------- | | `OR` | return empty list | validate single filter | validate all filters | | `AND` | return all items | validate single filter | validate all filters | | `NOT` | return all items | validate single filter | validate all filters | This example shows how an `undefined` parameter impacts the results returned by a query that uses the [`OR`](/orm/reference/prisma-client-reference#or) operator. ```ts interface FormData { name: string email?: string } const formData: FormData = { name: 'Emelie', } const users = await prisma.user.findMany({ where: { OR: [ { email: { contains: formData.email, }, }, ], }, }) // returns: [] ``` The query receives filters from a formData object, which includes an optional email property. In this instance, the value of the email property is `undefined`. When this query is run no data is returned. This is in contrast to the [`AND`](/orm/reference/prisma-client-reference#and) and [`NOT`](/orm/reference/prisma-client-reference#not-1) operators, which will both return all the users if you pass in an `undefined` value. > This is because passing an `undefined` value to an `AND` or `NOT` operator is the same > as passing nothing at all, meaning the `findMany` query in the example will run without any filters and return all the users. ```ts interface FormData { name: string email?: string } const formData: FormData = { name: 'Emelie', } const users = await prisma.user.findMany({ where: { AND: [ { email: { contains: formData.email, }, }, ], }, }) // returns: { id: 1, email: 'ems@boop.com', name: 'Emelie' } const users = await prisma.user.findMany({ where: { NOT: [ { email: { contains: formData.email, }, }, ], }, }) // returns: { id: 1, email: 'ems@boop.com', name: 'Emelie' } ``` --- # Working with Json fields URL: https://www.prisma.io/docs/orm/prisma-client/special-fields-and-types/working-with-json-fields Use the [`Json`](/orm/reference/prisma-schema-reference#json) Prisma ORM field type to read, write, and perform basic filtering on JSON types in the underlying database. In the following example, the `User` model has an optional `Json` field named `extendedPetsData`: ```prisma highlight=6;normal model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] //highlight-next-line extendedPetsData Json? } ``` Example field value: ```json { "pet1": { "petName": "Claudine", "petType": "House cat" }, "pet2": { "petName": "Sunny", "petType": "Gerbil" } } ``` The `Json` field supports a few additional types, such as `string` and `boolean`. These additional types exist to match the types supported by [`JSON.parse()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse): ```ts export type JsonValue = | string | number | boolean | null | JsonObject | JsonArray ``` ## Use cases for JSON fields Reasons to store data as JSON rather than representing data as related models include: - You need to store data that does not have a consistent structure - You are importing data from another system and do not want to map that data to Prisma models ## Reading a `Json` field You can use the `Prisma.JsonArray` and `Prisma.JsonObject` utility classes to work with the contents of a `Json` field: ```ts const { PrismaClient, Prisma } = require('@prisma/client') const user = await prisma.user.findFirst({ where: { id: 9, }, }) // Example extendedPetsData data: // [{ name: 'Bob the dog' }, { name: 'Claudine the cat' }] if ( user?.extendedPetsData && typeof user?.extendedPetsData === 'object' && Array.isArray(user?.extendedPetsData) ) { const petsObject = user?.extendedPetsData as Prisma.JsonArray const firstPet = petsObject[0] } ``` See also: [Advanced example: Update a nested JSON key value](#advanced-example-update-a-nested-json-key-value) ## Writing to a `Json` field The following example writes a JSON object to the `extendedPetsData` field: ```ts var json = [ { name: 'Bob the dog' }, { name: 'Claudine the cat' }, ] as Prisma.JsonArray const createUser = await prisma.user.create({ data: { email: 'birgitte@prisma.io', extendedPetsData: json, }, }) ``` > **Note**: JavaScript objects (for example, `{ extendedPetsData: "none"}`) are automatically converted to JSON. See also: [Advanced example: Update a nested JSON key value](#advanced-example-update-a-nested-json-key-value) ## Filter on a `Json` field (simple) You can filter rows of `Json` type. ### Filter on exact field value The following query returns all users where the value of `extendedPetsData` matches the `json` variable exactly: ```ts var json = { [{ name: 'Bob the dog' }, { name: 'Claudine the cat' }] } const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { equals: json, }, }, }) ``` The following query returns all users where the value of `extendedPetsData` does **not** match the `json` variable exactly: ```ts var json = { extendedPetsData: [{ name: 'Bob the dog' }, { name: 'Claudine the cat' }], } const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { not: json, }, }, }) ``` ## Filter on a `Json` field (advanced) You can also filter rows by the data inside a `Json` field. We call this **advanced `Json` filtering**. This functionality is supported by [PostgreSQL](/orm/overview/databases/postgresql) and [MySQL](/orm/overview/databases/mysql) only with [different syntaxes for the `path` option](#path-syntax-depending-on-database). PostgreSQL does not support [filtering on object key values in arrays](#filtering-on-object-key-value-inside-array). The availability of advanced `Json` filtering depends on your Prisma version: - v4.0.0 or later: advanced `Json` filtering is [generally available](/orm/more/releases#generally-available-ga). - From v2.23.0, but before v4.0.0: advanced `Json` filtering is a [preview feature](/orm/reference/preview-features/client-preview-features). Add `previewFeatures = ["filterJson"]` to your schema. [Learn more](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature). - Before v2.23.0: you can [filter on the exact `Json` field value](#filter-on-exact-field-value), but you cannot use the other features described in this section. ### `path` syntax depending on database The filters below use a `path` option to select specific parts of the `Json` value to filter on. The implementation of that filtering differs between connectors: - The [MySQL connector](/orm/overview/databases/mysql) uses [MySQL's implementation of JSON path](https://dev.mysql.com/doc/refman/8.0/en/json.html#json-path-syntax) - The [PostgreSQL connector](/orm/overview/databases/postgresql) uses the custom JSON functions and operators [supported in version 12 _and earlier_](https://www.postgresql.org/docs/11/functions-json.html) For example, the following is a valid MySQL `path` value: ``` $petFeatures.petName ``` The following is a valid PostgreSQL `path` value: ``` ["petFeatures", "petName"] ``` ### Filter on object property You can filter on a specific property inside a block of JSON. In the following examples, the value of `extendedPetsData` is a one-dimensional, unnested JSON object: ```json highlight=11;normal { "petName": "Claudine", "petType": "House cat" } ``` The following query returns all users where the value of `petName` is `"Claudine"`: ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: ['petName'], equals: 'Claudine', }, }, }) ``` ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: '$.petName', equals: 'Claudine', }, }, }) ``` The following query returns all users where the value of `petType` _contains_ `"cat"`: ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: ['petType'], string_contains: 'cat', }, }, }) ``` ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: '$.petType', string_contains: 'cat', }, }, }) ``` The following string filters are available: - [`string_contains`](/orm/reference/prisma-client-reference#string_contains) - [`string_starts_with`](/orm/reference/prisma-client-reference#string_starts_with) - [`string_ends_with`](/orm/reference/prisma-client-reference#string_ends_with) . To use case insensitive filter with these, you can use the [`mode`](/orm/reference/prisma-client-reference#mode) option: ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: ['petType'], string_contains: 'cat', mode: 'insensitive' }, }, }) ``` ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: '$.petType', string_contains: 'cat', mode: 'insensitive' }, }, }) ``` ### Filter on nested object property You can filter on nested JSON properties. In the following examples, the value of `extendedPetsData` is a JSON object with several levels of nesting. ```json { "pet1": { "petName": "Claudine", "petType": "House cat" }, "pet2": { "petName": "Sunny", "petType": "Gerbil", "features": { "eyeColor": "Brown", "furColor": "White and black" } } } ``` The following query returns all users where `"pet2"` → `"petName"` is `"Sunny"`: ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: ['pet2', 'petName'], equals: 'Sunny', }, }, }) ``` ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: '$.pet2.petName', equals: 'Sunny', }, }, }) ``` The following query returns all users where: - `"pet2"` → `"petName"` is `"Sunny"` - `"pet2"` → `"features"` → `"furColor"` contains `"black"` ```ts const getUsers = await prisma.user.findMany({ where: { AND: [ { extendedPetsData: { path: ['pet2', 'petName'], equals: 'Sunny', }, }, { extendedPetsData: { path: ['pet2', 'features', 'furColor'], string_contains: 'black', }, }, ], }, }) ``` ```ts const getUsers = await prisma.user.findMany({ where: { AND: [ { extendedPetsData: { path: '$.pet2.petName', equals: 'Sunny', }, }, { extendedPetsData: { path: '$.pet2.features.furColor', string_contains: 'black', }, }, ], }, }) ``` ### Filtering on an array value You can filter on the presence of a specific value in a scalar array (strings, integers). In the following example, the value of `extendedPetsData` is an array of strings: ```json ["Claudine", "Sunny"] ``` The following query returns all users with a pet named `"Claudine"`: ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { array_contains: ['Claudine'], }, }, }) ``` **Note**: In PostgreSQL, the value of `array_contains` must be an array and not a string, even if the array only contains a single value. ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { array_contains: 'Claudine', }, }, }) ``` The following array filters are available: - [`array_contains`](/orm/reference/prisma-client-reference#array_contains) - [`array_starts_with`](/orm/reference/prisma-client-reference#array_starts_with) - [`array_ends_with`](/orm/reference/prisma-client-reference#array_ends_with) ### Filtering on nested array value You can filter on the presence of a specific value in a scalar array (strings, integers). In the following examples, the value of `extendedPetsData` includes nested scalar arrays of names: ```json { "cats": { "owned": ["Bob", "Sunny"], "fostering": ["Fido"] }, "dogs": { "owned": ["Ella"], "fostering": ["Prince", "Empress"] } } ``` #### Scalar value arrays The following query returns all users that foster a cat named `"Fido"`: ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: ['cats', 'fostering'], array_contains: ['Fido'], }, }, }) ``` **Note**: In PostgreSQL, the value of `array_contains` must be an array and not a string, even if the array only contains a single value. ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: '$.cats.fostering', array_contains: 'Fido', }, }, }) ``` The following query returns all users that foster cats named `"Fido"` _and_ `"Bob"`: ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: ['cats', 'fostering'], array_contains: ['Fido', 'Bob'], }, }, }) ``` ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: '$.cats.fostering', array_contains: ['Fido', 'Bob'], }, }, }) ``` #### JSON object arrays ```ts const json = [{ status: 'expired', insuranceID: 92 }] const checkJson = await prisma.user.findMany({ where: { extendedPetsData: { path: ['insurances'], array_contains: json, }, }, }) ``` ```ts const json = { status: 'expired', insuranceID: 92 } const checkJson = await prisma.user.findMany({ where: { extendedPetsData: { path: '$.insurances', array_contains: json, }, }, }) ``` - If you are using PostgreSQL, you must pass in an array of objects to match, even if that array only contains one object: ```json5 [{ status: 'expired', insuranceID: 92 }] // PostgreSQL ``` If you are using MySQL, you must pass in a single object to match: ```json5 { status: 'expired', insuranceID: 92 } // MySQL ``` - If your filter array contains multiple objects, PostgreSQL will only return results if _all_ objects are present - not if at least one object is present. - You must set `array_contains` to a JSON object, not a string. If you use a string, Prisma Client escapes the quotation marks and the query will not return results. For example: ```ts array_contains: '[{"status": "expired", "insuranceID": 92}]' ``` is sent to the database as: ``` [{\"status\": \"expired\", \"insuranceID\": 92}] ``` ### Targeting an array element by index You can filter on the value of an element in a specific position. ```json { "owned": ["Bob", "Sunny"], "fostering": ["Fido"] } ``` ```ts const getUsers = await prisma.user.findMany({ where: { comments: { path: ['owned', '1'], string_contains: 'Bob', }, }, }) ``` ```ts const getUsers = await prisma.user.findMany({ where: { comments: { path: '$.owned[1]', string_contains: 'Bob', }, }, }) ``` ### Filtering on object key value inside array Depending on your provider, you can filter on the key value of an object inside an array. Filtering on object key values within an array is **only** supported by the [MySQL database connector](/orm/overview/databases/mysql). However, you can still [filter on the presence of entire JSON objects](#json-object-arrays). In the following example, the value of `extendedPetsData` is an array of objects with a nested `insurances` array, which contains two objects: ```json [ { "petName": "Claudine", "petType": "House cat", "insurances": [ { "insuranceID": 92, "status": "expired" }, { "insuranceID": 12, "status": "active" } ] }, { "petName": "Sunny", "petType": "Gerbil" }, { "petName": "Gerald", "petType": "Corn snake" }, { "petName": "Nanna", "petType": "Moose" } ] ``` The following query returns all users where at least one pet is a moose: ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: '$[*].petType', array_contains: 'Moose', }, }, }) ``` - `$[*]` is the root array of pet objects - `petType` matches the `petType` key in any pet object The following query returns all users where at least one pet has an expired insurance: ```ts const getUsers = await prisma.user.findMany({ where: { extendedPetsData: { path: '$[*].insurances[*].status', array_contains: 'expired', }, }, }) ``` - `$[*]` is the root array of pet objects - `insurances[*]` matches any `insurances` array inside any pet object - `status` matches any `status` key in any insurance object ## Advanced example: Update a nested JSON key value The following example assumes that the value of `extendedPetsData` is some variation of the following: ```json { "petName": "Claudine", "petType": "House cat", "insurances": [ { "insuranceID": 92, "status": "expired" }, { "insuranceID": 12, "status": "active" } ] } ``` The following example: 1. Gets all users 1. Change the `"status"` of each insurance object to `"expired"` 1. Get all users that have an expired insurance where the ID is `92` ```ts const userQueries: string | any[] = [] getUsers.forEach((user) => { if ( user.extendedPetsData && typeof user.extendedPetsData === 'object' && !Array.isArray(user.extendedPetsData) ) { const petsObject = user.extendedPetsData as Prisma.JsonObject const i = petsObject['insurances'] if (i && typeof i === 'object' && Array.isArray(i)) { const insurancesArray = i as Prisma.JsonArray insurancesArray.forEach((i) => { if (i && typeof i === 'object' && !Array.isArray(i)) { const insuranceObject = i as Prisma.JsonObject insuranceObject['status'] = 'expired' } }) const whereClause = Prisma.validator()({ id: user.id, }) const dataClause = Prisma.validator()({ extendedPetsData: petsObject, }) userQueries.push( prisma.user.update({ where: whereClause, data: dataClause, }) ) } } }) if (userQueries.length > 0) { console.log(userQueries.length + ' queries to run!') await prisma.$transaction(userQueries) } const json = [{ status: 'expired', insuranceID: 92 }] const checkJson = await prisma.user.findMany({ where: { extendedPetsData: { path: ['insurances'], array_contains: json, }, }, }) console.log(checkJson.length) ``` ```ts const userQueries: string | any[] = [] getUsers.forEach((user) => { if ( user.extendedPetsData && typeof user.extendedPetsData === 'object' && !Array.isArray(user.extendedPetsData) ) { const petsObject = user.extendedPetsData as Prisma.JsonObject const insuranceList = petsObject['insurances'] // is a Prisma.JsonArray if (Array.isArray(insuranceList)) { insuranceList.forEach((insuranceItem) => { if ( insuranceItem && typeof insuranceItem === 'object' && !Array.isArray(insuranceItem) ) { insuranceItem['status'] = 'expired' // is a Prisma.JsonObject } }) const whereClause = Prisma.validator()({ id: user.id, }) const dataClause = Prisma.validator()({ extendedPetsData: petsObject, }) userQueries.push( prisma.user.update({ where: whereClause, data: dataClause, }) ) } } }) if (userQueries.length > 0) { console.log(userQueries.length + ' queries to run!') await prisma.$transaction(userQueries) } const json = { status: 'expired', insuranceID: 92 } const checkJson = await prisma.user.findMany({ where: { extendedPetsData: { path: '$.insurances', array_contains: json, }, }, }) console.log(checkJson.length) ``` ## Using `null` Values There are two types of `null` values possible for a `JSON` field in an SQL database. - Database `NULL`: The value in the database is a `NULL`. - JSON `null`: The value in the database contains a JSON value that is `null`. To differentiate between these possibilities, we've introduced three _null enums_ you can use: - `JsonNull`: Represents the `null` value in JSON. - `DbNull`: Represents the `NULL` value in the database. - `AnyNull`: Represents both `null` JSON values and `NULL` database values. (Only when filtering) From v4.0.0, `JsonNull`, `DbNull`, and `AnyNull` are objects. Before v4.0.0, they were strings. - When filtering using any of the _null enums_ you can not use a shorthand and leave the `equals` operator off. - These _null enums_ do not apply to MongoDB because there the difference between a JSON `null` and a database `NULL` does not exist. - The _null enums_ do not apply to the `array_contains` operator in all databases because there can only be a JSON `null` within a JSON array. Since there cannot be a database `NULL` within a JSON array, `{ array_contains: null }` is not ambiguous. For example: ```prisma model Log { id Int @id meta Json } ``` Here is an example of using `AnyNull`: ```ts highlight=7;normal import { Prisma } from '@prisma/client' prisma.log.findMany({ where: { data: { meta: { equals: Prisma.AnyNull, }, }, }, }) ``` ### Inserting `null` Values This also applies to `create`, `update` and `upsert`. To insert a `null` value into a `Json` field, you would write: ```ts highlight=5;normal import { Prisma } from '@prisma/client' prisma.log.create({ data: { meta: Prisma.JsonNull, }, }) ``` And to insert a database `NULL` into a `Json` field, you would write: ```ts highlight=5;normal import { Prisma } from '@prisma/client' prisma.log.create({ data: { meta: Prisma.DbNull, }, }) ``` ### Filtering by `null` Values To filter by `JsonNull` or `DbNull`, you would write: ```ts highlight=6;normal import { Prisma } from '@prisma/client' prisma.log.findMany({ where: { meta: { equals: Prisma.AnyNull, }, }, }) ``` These _null enums_ do not apply to MongoDB because MongoDB does not differentiate between a JSON `null` and a database `NULL`. They also do not apply to the `array_contains` operator in all databases because there can only be a JSON `null` within a JSON array. Since there cannot be a database `NULL` within a JSON array, `{ array_contains: null }` is not ambiguous. ## Typed `Json` By default, `Json` fields are not typed in Prisma models. To accomplish strong typing inside of these fields, you will need to use an external package like [prisma-json-types-generator](https://www.npmjs.com/package/prisma-json-types-generator) to accomplish this. ### Using `prisma-json-types-generator` First, install and configure `prisma-json-types-generator` [according to the package's instructions](https://www.npmjs.com/package/prisma-json-types-generator#using-it). Then, assuming you have a model like the following: ```prisma no-copy model Log { id Int @id meta Json } ``` You can update it and type it by using [abstract syntax tree comments](/orm/prisma-schema/overview#comments) ```prisma highlight=4;normal file=schema.prisma showLineNumbers model Log { id Int @id //highlight-next-line /// [LogMetaType] meta Json } ``` Then, make sure you define the above type in a type declaration file included in your `tsconfig.json` ```ts file=types.ts showLineNumbers declare global { namespace PrismaJson { type LogMetaType = { timestamp: number; host: string } } } ``` Now, when working with `Log.meta` it will be strongly typed! ## `Json` FAQs ### Can you select a subset of JSON key/values to return? No - it is not yet possible to [select which JSON elements to return](https://github.com/prisma/prisma/issues/2431). Prisma Client returns the entire JSON object. ### Can you filter on the presence of a specific key? No - it is not yet possible to filter on the presence of a specific key. ### Is case insensitive filtering supported? No - [case insensitive filtering](https://github.com/prisma/prisma/issues/7390) is not yet supported. ### Can you sort an object property within a JSON value? No, [sorting object properties within a JSON value](https://github.com/prisma/prisma/issues/10346) (order-by-prop) is not currently supported. ### How to set a default value for JSON fields? When you want to set a `@default` value the `Json` type, you need to enclose it with double-quotes inside the `@default` attribute (and potentially escape any "inner" double-quotes using a backslash), for example: ```prisma model User { id Int @id @default(autoincrement()) json1 Json @default("[]") json2 Json @default("{ \"hello\": \"world\" }") } ``` --- # Working with scalar lists URL: https://www.prisma.io/docs/orm/prisma-client/special-fields-and-types/working-with-scalar-lists-arrays [Scalar lists](/orm/reference/prisma-schema-reference#-modifier) are represented by the `[]` modifier and are only available if the underlying database supports scalar lists. The following example has one scalar `String` list named `pets`: ```prisma highlight=4;normal model User { id Int @id @default(autoincrement()) name String //highlight-next-line pets String[] } ``` ```prisma highlight=4;normal model User { id String @id @default(auto()) @map("_id") @db.ObjectId name String //highlight-next-line pets String[] } ``` Example field value: ```json5 ['Fido', 'Snoopy', 'Brian'] ``` ## Setting the value of a scalar list The following example demonstrates how to [`set`](/orm/reference/prisma-client-reference#set-1) the value of a scalar list (`coinflips`) when you create a model: ```ts const createdUser = await prisma.user.create({ data: { email: 'eloise@prisma.io', coinflips: [true, true, true, false, true], }, }) ``` ## Unsetting the value of a scalar list This method is available on MongoDB only in versions [3.11.1](https://github.com/prisma/prisma/releases/tag/3.11.1) and later. The following example demonstrates how to [`unset`](/orm/reference/prisma-client-reference#unset) the value of a scalar list (`coinflips`): ```ts const createdUser = await prisma.user.create({ data: { email: 'eloise@prisma.io', coinflips: { unset: true, }, }, }) ``` Unlike `set: null`, `unset` removes the list entirely. ## Adding items to a scalar list Available for: - PostgreSQL in versions [2.15.0](https://github.com/prisma/prisma/releases/tag/2.15.0) and later - CockroachDB in versions [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0) and later - MongoDB in versions [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0) and later Use the [`push`](/orm/reference/prisma-client-reference#push) method to add a single value to a scalar list: ```ts const userUpdate = await prisma.user.update({ where: { id: 9, }, data: { coinflips: { push: true, }, }, }) ``` In earlier versions, you have to overwrite the entire value. The following example retrieves user, uses `push()` to add three new coin flips, and overwrites the `coinflips` field in an `update`: ```ts const user = await prisma.user.findUnique({ where: { email: 'eloise@prisma.io', }, }) if (user) { console.log(user.coinflips) user.coinflips.push(true, true, false) const updatedUser = await prisma.user.update({ where: { email: 'eloise@prisma.io', }, data: { coinflips: user.coinflips, }, }) console.log(updatedUser.coinflips) } ``` ## Filtering scalar lists Available for: - PostgreSQL in versions [2.15.0](https://github.com/prisma/prisma/releases/tag/2.15.0) and later - CockroachDB in versions [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0) and later - MongoDB in versions [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0) and later Use [scalar list filters](/orm/reference/prisma-client-reference#scalar-list-filters) to filter for records with scalar lists that match a specific condition. The following example returns all posts where the tags list includes `databases` _and_ `typescript`: ```ts const posts = await prisma.post.findMany({ where: { tags: { hasEvery: ['databases', 'typescript'], }, }, }) ``` ### `NULL` values in arrays This section applies to: - PostgreSQL in versions [2.15.0](https://github.com/prisma/prisma/releases/tag/2.15.0) and later - CockroachDB in versions [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0) and later When using scalar list filters with a relational database connector, array fields with a `NULL` value are not considered by the following conditions: - `NOT` (array does not contain X) - `isEmpty` (array is empty) This means that records you might expect to see are not returned. Consider the following examples: - The following query returns all posts where the `tags` **do not** include `databases`: ```ts const posts = await prisma.post.findMany({ where: { NOT: { tags: { has: 'databases', }, }, }, }) ``` - ✔ Arrays that do not contain `"databases"`, such as `{"typescript", "graphql"}` - ✔ Empty arrays, such as `[]` The query does not return: - ✘ `NULL` arrays, even though they do not contain `"databases"` The following query returns all posts where `tags` is empty: ```ts const posts = await prisma.post.findMany({ where: { tags: { isEmpty: true, }, }, }) ``` The query returns: - ✔ Empty arrays, such as `[]` The query does not return: - ✘ `NULL` arrays, even though they could be considered empty To work around this issue, you can set the default value of array fields to `[]`. --- # Working with compound IDs and unique constraints URL: https://www.prisma.io/docs/orm/prisma-client/special-fields-and-types/working-with-composite-ids-and-constraints Composite IDs and compound unique constraints can be defined in your Prisma schema using the [`@@id`](/orm/reference/prisma-schema-reference#id-1) and [`@@unique`](/orm/reference/prisma-schema-reference#unique-1) attributes. **MongoDB does not support `@@id`**
MongoDB does not support composite IDs, which means you cannot identify a model with a `@@id` attribute.
A composite ID or compound unique constraint uses the combined values of two fields as a primary key or identifier in your database table. In the following example, the `postId` field and `userId` field are used as a composite ID for a `Like` table: ```prisma highlight=22;normal model User { id Int @id @default(autoincrement()) name String post Post[] likes Like[] } model Post { id Int @id @default(autoincrement()) content String User User? @relation(fields: [userId], references: [id]) userId Int? likes Like[] } model Like { postId Int userId Int User User @relation(fields: [userId], references: [id]) Post Post @relation(fields: [postId], references: [id]) //highlight-next-line @@id([postId, userId]) } ``` Querying for records from the `Like` table (e.g. using `prisma.like.findMany()`) would return objects that look as follows: ```json { "postId": 1, "userId": 1 } ``` Although there are only two fields in the response, those two fields make up a compound ID named `postId_userId`. You can also create a named compound ID or compound unique constraint by using the `@@id` or `@@unique` attributes' `name` field. For example: ```prisma highlight=7;normal model Like { postId Int userId Int User User @relation(fields: [userId], references: [id]) Post Post @relation(fields: [postId], references: [id]) //highlight-next-line @@id(name: "likeId", [postId, userId]) } ```
## Where you can use compound IDs and unique constraints Compound IDs and compound unique constraints can be used when working with _unique_ data. Below is a list of Prisma Client functions that accept a compound ID or compound unique constraint in the `where` filter of the query: - `findUnique()` - `findUniqueOrThrow` - `delete` - `update` - `upsert` A composite ID and a composite unique constraint is also usable when creating relational data with `connect` and `connectOrCreate`. ## Filtering records by a compound ID or unique constraint Although your query results will not display a compound ID or unique constraint as a field, you can use these compound values to filter your queries for unique records: ```ts highlight=3-6;normal const like = await prisma.like.findUnique({ where: { likeId: { userId: 1, postId: 1, }, }, }) ``` Note composite ID and compound unique constraint keys are only available as filter options for _unique_ queries such as `findUnique()` and `findUniqueOrThrow`. See the [section](/orm/prisma-client/special-fields-and-types/working-with-composite-ids-and-constraints#where-you-can-use-compound-ids-and-unique-constraints) above for a list of places these fields may be used. ## Deleting records by a compound ID or unique constraint A compound ID or compound unique constraint may be used in the `where` filter of a `delete` query: ```ts highlight=3-6;normal const like = await prisma.like.delete({ where: { likeId: { userId: 1, postId: 1, }, }, }) ``` ## Updating and upserting records by a compound ID or unique constraint A compound ID or compound unique constraint may be used in the `where` filter of an `update` query: ```ts highlight=3-6;normal const like = await prisma.like.update({ where: { likeId: { userId: 1, postId: 1, }, }, data: { postId: 2, }, }) ``` They may also be used in the `where` filter of an `upsert` query: ```ts highlight=3-6;normal await prisma.like.upsert({ where: { likeId: { userId: 1, postId: 1, }, }, update: { userId: 2, }, create: { userId: 2, postId: 1, }, }) ``` ## Filtering relation queries by a compound ID or unique constraint Compound IDs and compound unique constraint can also be used in the `connect` and `connectOrCreate` keys used when connecting records to create a relationship. For example, consider this query: ```ts highlight=6-9;normal await prisma.user.create({ data: { name: 'Alice', likes: { connect: { likeId: { postId: 1, userId: 2, }, }, }, }, }) ``` The `likeId` compound ID is used as the identifier in the `connect` object that is used to locate the `Like` table's record that will be linked to the new user: `"Alice"`. Similarly, the `likeId` can be used in `connectOrCreate`'s `where` filter to attempt to locate an existing record in the `Like` table: ```ts highlight=10-13;normal await prisma.user.create({ data: { name: 'Alice', likes: { connectOrCreate: { create: { postId: 1, }, where: { likeId: { postId: 1, userId: 1, }, }, }, }, }, }) ``` --- # Fields & types URL: https://www.prisma.io/docs/orm/prisma-client/special-fields-and-types/index This section covers various special fields and types you can use with Prisma Client. ## Working with `Decimal` `Decimal` fields are represented by the [`Decimal.js` library](https://mikemcl.github.io/decimal.js/). The following example demonstrates how to import and use `Prisma.Decimal`: ```ts import { PrismaClient, Prisma } from '@prisma/client' const newTypes = await prisma.sample.create({ data: { cost: new Prisma.Decimal(24.454545), }, }) ```
You can also perform arithmetic operations: ```ts import { PrismaClient, Prisma } from '@prisma/client' const newTypes = await prisma.sample.create({ data: { cost: new Prisma.Decimal(24.454545).plus(1), }, }) ``` `Prisma.Decimal` uses Decimal.js, see [Decimal.js docs](https://mikemcl.github.io/decimal.js) to learn more. :::warning The use of the `Decimal` field [is not currently supported in MongoDB](https://github.com/prisma/prisma/issues/12637). ::: ## Working with `BigInt` ### Overview `BigInt` fields are represented by the [`BigInt` type](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) (Node.js 10.4.0+ required). The following example demonstrates how to use the `BigInt` type: ```ts import { PrismaClient, Prisma } from '@prisma/client' const newTypes = await prisma.sample.create({ data: { revenue: BigInt(534543543534), }, }) ``` ### Serializing `BigInt` Prisma Client returns records as plain JavaScript objects. If you attempt to use `JSON.stringify` on an object that includes a `BigInt` field, you will see the following error: ``` Do not know how to serialize a BigInt ``` To work around this issue, use a customized implementation of `JSON.stringify`: ```js JSON.stringify( this, (key, value) => (typeof value === 'bigint' ? value.toString() : value) // return everything else unchanged ) ``` ## Working with `Bytes` `Bytes` fields are represented by the [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) type. The following example demonstrates how to use the `Uint8Array` type: ```ts import { PrismaClient, Prisma } from '@prisma/client' const newTypes = await prisma.sample.create({ data: { myField: new Uint8Array([1, 2, 3, 4]), }, }) ``` Note that **before Prisma v6**, `Bytes` were represented by the [`Buffer`](https://nodejs.org/api/buffer.html) type: ```ts import { PrismaClient, Prisma } from '@prisma/client' const newTypes = await prisma.sample.create({ data: { myField: Buffer.from([1, 2, 3, 4]), }, }) ``` Learn more in the [upgrade guide to v6](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6). ## Working with `DateTime` :::note There currently is a [bug](https://github.com/prisma/prisma/issues/9516) that doesn't allow you to pass in `DateTime` values as strings and produces a runtime error when you do. `DateTime` values need to be passed as [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) objects (i.e. `new Date('2024-12-04')` instead of `'2024-12-04'`). ::: When creating records that have fields of type [`DateTime`](/orm/reference/prisma-schema-reference#datetime), Prisma Client accepts values as [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) objects adhering to the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) standard. Consider the following schema: ```prisma model User { id Int @id @default(autoincrement()) birthDate DateTime? } ``` Here are some examples for creating new records: ##### Jan 01, 1998; 00 h 00 min and 000 ms ```ts await prisma.user.create({ data: { birthDate: new Date('1998') } }) ``` ##### Dec 01, 1998; 00 h 00 min and 000 ms ```ts await prisma.user.create({ data: { birthDate: new Date('1998-12') } }) ``` ##### Dec 24, 1998; 00 h 00 min and 000 ms ```ts await prisma.user.create({ data: { birthDate: new Date('1998-12-24') } }) ``` ##### Dec 24, 1998; 06 h 22 min 33s and 444 ms ```ts await prisma.user.create({ data: { birthDate: new Date('1998-12-24T06:22:33.444Z') } }) ``` ## Working with `Json` See: [Working with `Json` fields](/orm/prisma-client/special-fields-and-types/working-with-json-fields) ## Working with scalar lists / scalar arrays See: [Working with scalar lists / arrays](/orm/prisma-client/special-fields-and-types/working-with-scalar-lists-arrays) ## Working with composite IDs and compound unique constraints See: [Working with composite IDs and compound unique constraints](/orm/prisma-client/special-fields-and-types/working-with-composite-ids-and-constraints) --- # `model`: Add custom methods to your models URL: https://www.prisma.io/docs/orm/prisma-client/client-extensions/model Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0. You can use the `model` [Prisma Client extensions](/orm/prisma-client/client-extensions) component type to add custom methods to your models. Possible uses for the `model` component include the following: - New operations to operate alongside existing Prisma Client operations, such as `findMany` - Encapsulated business logic - Repetitive operations - Model-specific utilities ## Add a custom method Use the `$extends` [client-level method](/orm/reference/prisma-client-reference#client-methods) to create an _extended client_. An extended client is a variant of the standard Prisma Client that is wrapped by one or more extensions. Use the `model` extension component to add methods to models in your schema. ### Add a custom method to a specific model To extend a specific model in your schema, use the following structure. This example adds a method to the `user` model. ```ts const prisma = new PrismaClient().$extends({ name?: '', // (optional) names the extension for error logs model?: { user: { ... } // in this case, we extend the `user` model }, }); ``` #### Example The following example adds a method called `signUp` to the `user` model. This method creates a new user with the specified email address: ```ts const prisma = new PrismaClient().$extends({ model: { user: { async signUp(email: string) { await prisma.user.create({ data: { email } }) }, }, }, }) ``` You would call `signUp` in your application as follows: ```ts const user = await prisma.user.signUp('john@prisma.io') ``` ### Add a custom method to all models in your schema To extend _all_ models in your schema, use the following structure: ```ts const prisma = new PrismaClient().$extends({ name?: '', // `name` is an optional field that you can use to name the extension for error logs model?: { $allModels: { ... } }, }) ``` #### Example The following example adds an `exists` method to all models. ```ts const prisma = new PrismaClient().$extends({ model: { $allModels: { async exists( this: T, where: Prisma.Args['where'] ): Promise { // Get the current model at runtime const context = Prisma.getExtensionContext(this) const result = await (context as any).findFirst({ where }) return result !== null }, }, }, }) ``` You would call `exists` in your application as follows: ```ts // `exists` method available on all models await prisma.user.exists({ name: 'Alice' }) await prisma.post.exists({ OR: [{ title: { contains: 'Prisma' } }, { content: { contains: 'Prisma' } }], }) ``` ## Call a custom method from another custom method You can call a custom method from another custom method, if the two methods are declared on the same model. For example, you can call a custom method on the `user` model from another custom method on the `user` model. It does not matter if the two methods are declared in the same extension or in different extensions. To do so, use `Prisma.getExtensionContext(this).methodName`. Note that you cannot use `prisma.user.methodName`. This is because `prisma` is not extended yet, and therefore does not contain the new method. For example: ```ts const prisma = new PrismaClient().$extends({ model: { user: { firstMethod() { ... }, secondMethod() { Prisma.getExtensionContext(this).firstMethod() } } } }) ``` ## Get the current model name at runtime This feature is available from version 4.9.0. You can get the name of the current model at runtime with `Prisma.getExtensionContext(this).$name`. You might use this to write out the model name to a log, to send the name to another service, or to branch your code based on the model. For example: ```ts // `context` refers to the current model const context = Prisma.getExtensionContext(this) // `context.name` returns the name of the current model console.log(context.name) // Usage await(context as any).findFirst({ args }) ``` Refer to [Add a custom method to all models in your schema](#example-1) for a concrete example for retrieving the current model name at runtime. ## Advanced type safety: type utilities for defining generic extensions You can improve the type-safety of `model` components in your shared extensions with [type utilities](/orm/prisma-client/client-extensions/type-utilities). --- # `client`: Add methods to Prisma Client URL: https://www.prisma.io/docs/orm/prisma-client/client-extensions/client Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0. You can use the `client` [Prisma Client extensions](/orm/prisma-client/client-extensions) component to add top-level methods to Prisma Client. ## Extend Prisma Client Use the `$extends` [client-level method](/orm/reference/prisma-client-reference#client-methods) to create an _extended client_. An extended client is a variant of the standard Prisma Client that is wrapped by one or more extensions. Use the `client` extension component to add top-level methods to Prisma Client. To add a top-level method to Prisma Client, use the following structure: ```ts const prisma = new PrismaClient().$extends({ client?: { ... } }) ``` ### Example The following example uses the `client` component to add two methods to Prisma Client: - `$log` outputs a message. - `$totalQueries` returns the number of queries executed by the current client instance. It uses the [metrics](/orm/prisma-client/observability-and-logging/metrics) feature to collect this information. To use metrics in your project, you must enable the `metrics` feature flag in the `generator` block of your `schema.prisma` file. [Learn more](/orm/prisma-client/observability-and-logging/metrics#2-enable-the-feature-flag-in-the-prisma-schema-file). ```ts const prisma = new PrismaClient().$extends({ client: { $log: (s: string) => console.log(s), async $totalQueries() { const index_prisma_client_queries_total = 0 // Prisma.getExtensionContext(this) in the following block // returns the current client instance const metricsCounters = await ( await Prisma.getExtensionContext(this).$metrics.json() ).counters return metricsCounters[index_prisma_client_queries_total].value }, }, }) async function main() { prisma.$log('Hello world') const totalQueries = await prisma.$totalQueries() console.log(totalQueries) } ``` --- # `query`: Create custom Prisma Client queries URL: https://www.prisma.io/docs/orm/prisma-client/client-extensions/query Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0. You can use the `query` [Prisma Client extensions](/orm/prisma-client/client-extensions) component type to hook into the query life-cycle and modify an incoming query or its result. You can use Prisma Client extensions `query` component to create independent clients. This provides an alternative to [middlewares](/orm/prisma-client/client-extensions/middleware). You can bind one client to a specific filter or user, and another client to another filter or user. For example, you might do this to get [user isolation](/orm/prisma-client/client-extensions#extended-clients) in a row-level security (RLS) extension. In addition, unlike middlewares the `query` extension component gives you end-to-end type safety. [Learn more about `query` extensions versus middlewares](#query-extensions-versus-middlewares). ## Extend Prisma Client query operations Use the `$extends` [client-level method](/orm/reference/prisma-client-reference#client-methods) to create an [extended client](/orm/prisma-client/client-extensions#about-prisma-client-extensions). An extended client is a variant of the standard Prisma Client that is wrapped by one or more extensions. Use the `query` extension component to modify queries. You can modify a custom query in the following: - [A specific operation in a specific model](#modify-a-specific-operation-in-a-specific-model) - [A specific operation in all models of your schema](#modify-a-specific-operation-in-all-models-of-your-schema) - [All Prisma Client operations](#modify-all-prisma-client-operations) - [All operations in a specific model](#modify-all-operations-in-a-specific-model) - [All operations in all models of your schema](#modify-all-operations-in-all-models-of-your-schema) - [A specific top-level raw query operation](#modify-a-top-level-raw-query-operation) To create a custom query, use the following structure: ```ts const prisma = new PrismaClient().$extends({ name?: 'name', query?: { user: { ... } // in this case, we add a query to the `user` model }, }); ``` The properties are as follows: - `name`: (optional) specifies a name for the extension that appears in error logs. - `query`: defines a custom query. ### Modify a specific operation in a specific model The `query` object can contain functions that map to the names of the [Prisma Client operations](/orm/reference/prisma-client-reference#model-queries), such as `findUnique()`, `findFirst`, `findMany`, `count`, and `create`. The following example modifies `user.findMany` to a use a customized query that finds only users who are older than 18 years: ```ts const prisma = new PrismaClient().$extends({ query: { user: { async findMany({ model, operation, args, query }) { // take incoming `where` and set `age` args.where = { ...args.where, age: { gt: 18 } } return query(args) }, }, }, }) await prisma.user.findMany() // returns users whose age is greater than 18 ``` In the above example, a call to `prisma.user.findMany` triggers `query.user.findMany`. Each callback receives a type-safe `{ model, operation, args, query }` object that describes the query. This object has the following properties: - `model`: the name of the containing model for the query that we want to extend. In the above example, the `model` is a string of type `"User"`. - `operation`: the name of the operation being extended and executed. In the above example, the `operation` is a string of type `"findMany"`. - `args`: the specific query input information to be extended. This is a type-safe object that you can mutate before the query happens. You can mutate any of the properties in `args`. Exception: you cannot mutate `include` or `select` because that would change the expected output type and break type safety. - `query`: a promise for the result of the query. - You can use `await` and then mutate the result of this promise, because its value is type-safe. TypeScript catches any unsafe mutations on the object. ### Modify a specific operation in all models of your schema To extend the queries in all the models of your schema, use `$allModels` instead of a specific model name. For example: ```ts const prisma = new PrismaClient().$extends({ query: { $allModels: { async findMany({ model, operation, args, query }) { // set `take` and fill with the rest of `args` args = { ...args, take: 100 } return query(args) }, }, }, }) ``` ### Modify all operations in a specific model Use `$allOperations` to extend all operations in a specific model. For example, the following code applies a custom query to all operations on the `user` model: ```ts const prisma = new PrismaClient().$extends({ query: { user: { $allOperations({ model, operation, args, query }) { /* your custom logic here */ return query(args) }, }, }, }) ``` ### Modify all Prisma Client operations Use the `$allOperations` method to modify all query methods present in Prisma Client. The `$allOperations` can be used on both model operations and raw queries. You can modify all methods as follows: ```ts const prisma = new PrismaClient().$extends({ query: { $allOperations({ model, operation, args, query }) { /* your custom logic for modifying all Prisma Client operations here */ return query(args) }, }, }) ``` In the event a [raw query](/orm/prisma-client/using-raw-sql/raw-queries) is invoked, the `model` argument passed to the callback will be `undefined`. For example, you can use the `$allOperations` method to log queries as follows: ```ts const prisma = new PrismaClient().$extends({ query: { async $allOperations({ operation, model, args, query }) { const start = performance.now() const result = await query(args) const end = performance.now() const time = end - start console.log( util.inspect( { model, operation, args, time }, { showHidden: false, depth: null, colors: true } ) ) return result }, }, }) ``` ### Modify all operations in all models of your schema Use `$allModels` and `$allOperations` to extend all operations in all models of your schema. To apply a custom query to all operations on all models of your schema: ```ts const prisma = new PrismaClient().$extends({ query: { $allModels: { $allOperations({ model, operation, args, query }) { /* your custom logic for modifying all operations on all models here */ return query(args) }, }, }, }) ``` ### Modify a top-level raw query operation To apply custom behavior to a specific top-level raw query operation, use the name of a top-level raw query function instead of a model name: ```ts copy const prisma = new PrismaClient().$extends({ query: { $queryRaw({ args, query, operation }) { // handle $queryRaw operation return query(args) }, $executeRaw({ args, query, operation }) { // handle $executeRaw operation return query(args) }, $queryRawUnsafe({ args, query, operation }) { // handle $queryRawUnsafe operation return query(args) }, $executeRawUnsafe({ args, query, operation }) { // handle $executeRawUnsafe operation return query(args) }, }, }) ``` ```ts copy const prisma = new PrismaClient().$extends({ query: { $runCommandRaw({ args, query, operation }) { // handle $runCommandRaw operation return query(args) }, }, }) ``` ### Mutate the result of a query You can use `await` and then mutate the result of the `query` promise. ```ts const prisma = new PrismaClient().$extends({ query: { user: { async findFirst({ model, operation, args, query }) { const user = await query(args) if (user.password !== undefined) { user.password = '******' } return user }, }, }, }) ``` We include the above example to show that this is possible. However, for performance reasons we recommend that you use the [`result` component type](/orm/prisma-client/client-extensions/result) to override existing fields. The `result` component type usually gives better performance in this situation because it computes only on access. The `query` component type computes after query execution. ## Wrap a query into a batch transaction You can wrap your extended queries into a [batch transaction](/orm/prisma-client/queries/transactions). For example, you can use this to enact row-level security (RLS). The following example extends `findFirst` so that it runs in a batch transaction. ```ts const transactionExtension = Prisma.defineExtension((prisma) => prisma.$extends({ query: { user: { // Get the input `args` and a callback to `query` async findFirst({ args, query, operation }) { const [result] = await prisma.$transaction([query(args)]) // wrap the query in a batch transaction, and destructure the result to return an array return result // return the first result found in the array }, }, }, }) ) const prisma = new PrismaClient().$extends(transactionExtension) ``` ## Query extensions versus middlewares You can use query extensions or [middlewares](/orm/prisma-client/client-extensions/middleware) to hook into the query life-cycle and modify an incoming query or its result. Client extensions and middlewares differ in the following ways: - Middlewares always apply globally to the same client. Client extensions are isolated, unless you deliberately combine them. [Learn more about client extensions](/orm/prisma-client/client-extensions#about-prisma-client-extensions). - For example, in a row-level security (RLS) scenario, you can keep each user in an entirely separate client. With middlewares, all users are active in the same client. - During application execution, with extensions you can choose from one or more extended clients, or the standard Prisma Client. With middlewares, you cannot choose which client to use, because there is only one global client. - Extensions benefit from end-to-end type safety and inference, but middlewares don't. You can use Prisma Client extensions in all scenarios where middlewares can be used. ### If you use the `query` extension component and middlewares If you use the `query` extension component and middlewares in your project, then the following rules and priorities apply: - In your application code, you must declare all your middlewares on the main Prisma Client instance. You cannot declare them on an extended client. - In situations where middlewares and extensions with a `query` component execute, Prisma Client executes the middlewares before it executes the extensions with the `query` component. Prisma Client executes the individual middlewares and extensions in the order in which you instantiated them with `$use` or `$extends`. --- # `result`: Add custom fields and methods to query results URL: https://www.prisma.io/docs/orm/prisma-client/client-extensions/result Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0. You can use the `result` [Prisma Client extensions](/orm/prisma-client/client-extensions) component type to add custom fields and methods to query results. Use the `$extends` [client-level method](/orm/reference/prisma-client-reference#client-methods) to create an _extended client_. An extended client is a variant of the standard Prisma Client that is wrapped by one or more extensions. To add a custom [field](#add-a-custom-field-to-query-results) or [method](#add-a-custom-method-to-the-result-object) to query results, use the following structure. In this example, we add the custom field `myComputedField` to the result of a `user` model query. ```ts const prisma = new PrismaClient().$extends({ name?: 'name', result?: { user: { // in this case, we extend the `user` model myComputedField: { // the name of the new computed field needs: { ... }, compute() { ... } }, }, }, }); ``` The parameters are as follows: - `name`: (optional) specifies a name for the extension that appears in error logs. - `result`: defines new fields and methods to the query results. - `needs`: an object which describes the dependencies of the result field. - `compute`: a method that defines how the virtual field is computed when it is accessed. ## Add a custom field to query results You can use the `result` extension component to add fields to query results. These fields are computed at runtime and are type-safe. In the following example, we add a new virtual field called `fullName` to the `user` model. ```ts const prisma = new PrismaClient().$extends({ result: { user: { fullName: { // the dependencies needs: { firstName: true, lastName: true }, compute(user) { // the computation logic return `${user.firstName} ${user.lastName}` }, }, }, }, }) const user = await prisma.user.findFirst() // return the user's full name, such as "John Doe" console.log(user.fullName) ``` In above example, the input `user` of `compute` is automatically typed according to the object defined in `needs`. `firstName` and `lastName` are of type `string`, because they are specified in `needs`. If they are not specified in `needs`, then they cannot be accessed. ## Re-use a computed field in another computed field The following example computes a user's title and full name in a type-safe way. `titleFullName` is a computed field that reuses the `fullName` computed field. ```ts const prisma = new PrismaClient() .$extends({ result: { user: { fullName: { needs: { firstName: true, lastName: true }, compute(user) { return `${user.firstName} ${user.lastName}` }, }, }, }, }) .$extends({ result: { user: { titleFullName: { needs: { title: true, fullName: true }, compute(user) { return `${user.title} (${user.fullName})` }, }, }, }, }) ``` ### Considerations for fields - For performance reasons, Prisma Client computes results on access, not on retrieval. - You can only create computed fields that are based on scalar fields. - You can only use computed fields with `select` and you cannot aggregate them. For example: ```ts const user = await prisma.user.findFirst({ select: { email: true }, }) console.log(user.fullName) // undefined ``` ## Add a custom method to the result object You can use the `result` component to add methods to query results. The following example adds a new method, `save` to the result object. ```ts const prisma = new PrismaClient().$extends({ result: { user: { save: { needs: { id: true }, compute(user) { return () => prisma.user.update({ where: { id: user.id }, data: user }) }, }, }, }, }) const user = await prisma.user.findUniqueOrThrow({ where: { id: someId } }) user.email = 'mynewmail@mailservice.com' await user.save() ``` ## Using `omit` query option with `result` extension component You can use the [`omit` (Preview) option](/orm/reference/prisma-client-reference#omit) with [custom fields](#add-a-custom-field-to-query-results) and fields needed by custom fields. ### `omit` fields needed by custom fields from query result If you `omit` a field that is a dependency of a custom field, it will still be read from the database even though it will not be included in the query result. The following example omits the `password` field, which is a dependency of the custom field `sanitizedPassword`: ```ts const xprisma = prisma.$extends({ result: { user: { sanitizedPassword: { needs: { password: true }, compute(user) { return sanitize(user.password) }, }, }, }, }) const user = await xprisma.user.findFirstOrThrow({ omit: { password: true, }, }) ``` In this case, although `password` is omitted from the result, it will still be queried from the database because it is a dependency of the `sanitizedPassword` custom field. ### `omit` custom field and dependencies from query result To ensure omitted fields are not queried from the database at all, you must omit both the custom field and its dependencies. The following example omits both the custom field `sanitizedPassword` and the dependent `password` field: ```ts const xprisma = prisma.$extends({ result: { user: { sanitizedPassword: { needs: { password: true }, compute(user) { return sanitize(user.password) }, }, }, }, }) const user = await xprisma.user.findFirstOrThrow({ omit: { sanitizedPassword: true, password: true, }, }) ``` In this case, omitting both `password` and `sanitizedPassword` will exclude both from the result as well as prevent the `password` field from being read from the database. ## Limitation As of now, Prisma Client's result extension component does not support relation fields. This means that you cannot create custom fields or methods based on related models or fields in a relational relationship (e.g., user.posts, post.author). The needs parameter can only reference scalar fields within the same model. Follow [issue #20091 on GitHub](https://github.com/prisma/prisma/issues/20091). ```ts const prisma = new PrismaClient().$extends({ result: { user: { postsCount: { needs: { posts: true }, // This will not work because posts is a relation field compute(user) { return user.posts.length; // Accessing a relation is not allowed }, }, }, }, }) ``` --- # Shared Prisma Client extensions URL: https://www.prisma.io/docs/orm/prisma-client/client-extensions/shared-extensions You can share your [Prisma Client extensions](/orm/prisma-client/client-extensions) with other users, either as packages or as modules, and import extensions that other users create into your project. If you would like to build a shareable extension, we also recommend using the [`prisma-client-extension-starter`](https://github.com/prisma/prisma-client-extension-starter) template. To explore examples of Prisma's official Client extensions and those made by the community, visit [this](/orm/prisma-client/client-extensions/extension-examples) page. ## Install a shared, packaged extension In your project, you can install any Prisma Client extension that another user has published to `npm`. To do so, run the following command: ```terminal npm install prisma-extension- ``` For example, if the package name for an available extension is `prisma-extension-find-or-create`, you could install it as follows: ```terminal npm install prisma-extension-find-or-create ``` To import the `find-or-create` extension from the example above, and wrap your client instance with it, you could use the following code. This example assumes that the extension name is `findOrCreate`. ```ts import findOrCreate from 'prisma-extension-find-or-create' const prisma = new PrismaClient().$extends(findOrCreate) const user = await prisma.user.findOrCreate() ``` When you call a method in an extension, use the constant name from your `$extends` statement, not `prisma`. In the above example,`xprisma.user.findOrCreate` works, but `prisma.user.findOrCreate` does not, because the original `prisma` is not modified. ## Create a shareable extension When you want to create extensions other users can use, and that are not tailored just for your schema, Prisma ORM provides utilities to allow you to create shareable extensions. To create a shareable extension: 1. Define the extension as a module using `Prisma.defineExtension` 2. Use one of the methods that begin with the `$all` prefix such as [`$allModels`](/orm/prisma-client/client-extensions/model#add-a-custom-method-to-all-models-in-your-schema) or [`$allOperations`](/orm/prisma-client/client-extensions/query#modify-all-prisma-client-operations) ### Define an extension Use the `Prisma.defineExtension` method to make your extension shareable. You can use it to package the extension to either separate your extensions into a separate file or share it with other users as an npm package. The benefit of `Prisma.defineExtension` is that it provides strict type checks and auto completion for authors of extension in development and users of shared extensions. ### Use a generic method Extensions that contain methods under `$allModels` apply to every model instead of a specific one. Similarly, methods under `$allOperations` apply to a client instance as a whole and not to a named component, e.g. `result` or `query`. You do not need to use the `$all` prefix with the [`client`](/orm/prisma-client/client-extensions/client) component, because the `client` component always applies to the client instance. For example, a generic extension might take the following form: ```ts export default Prisma.defineExtension({ name: 'prisma-extension-find-or-create', //Extension name model: { $allModels: { // new method findOrCreate(/* args */) { /* code for the new method */ return query(args) }, }, }, }) ``` Refer to the following pages to learn the different ways you can modify Prisma Client operations: - [Modify all Prisma Client operations](/orm/prisma-client/client-extensions/query#modify-all-prisma-client-operations) - [Modify a specific operation in all models of your schema](/orm/prisma-client/client-extensions/query#modify-a-specific-operation-in-all-models-of-your-schema) - [Modify all operations in all models of your schema](/orm/prisma-client/client-extensions/query#modify-all-operations-in-all-models-of-your-schema)
For versions earlier than 4.16.0 The `Prisma` import is available from a different path shown in the snippet below: ```ts import { Prisma } from '@prisma/client/scripts/default-index' export default Prisma.defineExtension({ name: 'prisma-extension-', }) ```
### Publishing the shareable extension to npm You can then share the extension on `npm`. When you choose a package name, we recommend that you use the `prisma-extension-` convention, to make it easier to find and install. ### Call a client-level method from your packaged extension :::warning There's currently a limitation for extensions that reference a `PrismaClient` and call a client-level method, like the example below. If you trigger the extension from inside a [transaction](/orm/prisma-client/queries/transactions) (interactive or batched), the extension code will issue the queries in a new connection and ignore the current transaction context. Learn more in this issue on GitHub: [Client extensions that require use of a client-level method silently ignore transactions](https://github.com/prisma/prisma/issues/20678). ::: In the following situations, you need to refer to a Prisma Client instance that your extension wraps: - When you want to use a [client-level method](/orm/reference/prisma-client-reference#client-methods), such as `$queryRaw`, in your packaged extension. - When you want to chain multiple `$extends` calls in your packaged extension. However, when someone includes your packaged extension in their project, your code cannot know the details of the Prisma Client instance. You can refer to this client instance as follows: ```ts Prisma.defineExtension((client) => { // The Prisma Client instance that the extension user applies the extension to return client.$extends({ name: 'prisma-extension-', }) }) ``` For example: ```ts export default Prisma.defineExtension((client) => { return client.$extends({ name: 'prisma-extension-find-or-create', query: { $allModels: { async findOrCreate({ args, query, operation }) { return (await client.$transaction([query(args)]))[0] }, }, }, }) }) ``` ### Advanced type safety: type utilities for defining generic extensions You can improve the type-safety of your shared extensions using [type utilities](/orm/prisma-client/client-extensions/type-utilities). --- # Type utilities URL: https://www.prisma.io/docs/orm/prisma-client/client-extensions/type-utilities Several type utilities exist within Prisma Client that can assist in the creation of highly type-safe extensions. ## Type Utilities [Prisma Client type utilities](/orm/prisma-client/type-safety) are utilities available within your application and Prisma Client extensions and provide useful ways of constructing safe and extendable types for your extension. The type utilities available are: - `Exact`: Enforces strict type safety on `Input`. `Exact` makes sure that a generic type `Input` strictly complies with the type that you specify in `Shape`. It [narrows](https://www.typescriptlang.org/docs/handbook/2/narrowing.html) `Input` down to the most precise types. - `Args`: Retrieves the input arguments for any given model and operation. This is particularly useful for extension authors who want to do the following: - Re-use existing types to extend or modify them. - Benefit from the same auto-completion experience as on existing operations. - `Result`: Takes the input arguments and provides the result for a given model and operation. You would usually use this in conjunction with `Args`. As with `Args`, `Result` helps you to re-use existing types to extend or modify them. - `Payload`: Retrieves the entire structure of the result, as scalars and relations objects for a given model and operation. For example, you can use this to determine which keys are scalars or objects at a type level. The following example creates a new operation, `exists`, based on `findFirst`. It has all of the arguments that `findFirst`. ```ts const prisma = new PrismaClient().$extends({ model: { $allModels: { // Define a new `exists` operation on all models // T is a generic type that corresponds to the current model async exists( // `this` refers to the current type, e.g. `prisma.user` at runtime this: T, // The `exists` function will use the `where` arguments from the current model, `T`, and the `findFirst` operation where: Prisma.Args['where'] ): Promise { // Retrieve the current model at runtime const context = Prisma.getExtensionContext(this) // Prisma Client query that retrieves data based const result = await (context as any).findFirst({ where }) return result !== null }, }, }, }) async function main() { const user = await prisma.user.exists({ name: 'Alice' }) const post = await prisma.post.exists({ OR: [ { title: { contains: 'Prisma' } }, { content: { contains: 'Prisma' } }, ], }) } ``` ## Add a custom property to a method The following example illustrates how you can add custom arguments, to a method in an extension: ```ts highlight=16 type CacheStrategy = { swr: number ttl: number } const prisma = new PrismaClient().$extends({ model: { $allModels: { findMany( this: T, args: Prisma.Exact< A, // For the `findMany` method, use the arguments from model `T` and the `findMany` method // and intersect it with `CacheStrategy` as part of `findMany` arguments Prisma.Args & CacheStrategy > ): Prisma.Result { // method implementation with the cache strategy }, }, }, }) async function main() { await prisma.post.findMany({ cacheStrategy: { ttl: 360, swr: 60, }, }) } ``` The example here is only conceptual. For the actual caching to work, you will have to implement the logic. If you're interested in a caching extension/ service, we recommend taking a look at [Prisma Accelerate](https://www.prisma.io/accelerate). --- # Shared packages & examples URL: https://www.prisma.io/docs/orm/prisma-client/client-extensions/extension-examples ## Extensions made by Prisma The following is a list of extensions we've built at Prisma: | Extension | Description | | :------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------- | | [`@prisma/extension-accelerate`](https://www.npmjs.com/package/@prisma/extension-accelerate) | Enables [Accelerate](https://www.prisma.io/accelerate), a global database cache available in 300+ locations with built-in connection pooling | | [`@prisma/extension-read-replicas`](https://github.com/prisma/extension-read-replicas) | Adds read replica support to Prisma Client | ## Extensions made by Prisma's community The following is a list of extensions created by the community. If you want to create your own package, refer to the [Shared Prisma Client extensions](/orm/prisma-client/client-extensions/shared-extensions) documentation. | Extension | Description | | :--------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------- | | [`prisma-extension-supabase-rls`](https://github.com/dthyresson/prisma-extension-supabase-rls) | Adds support for Supabase Row Level Security with Prisma | | [`prisma-extension-bark`](https://github.com/adamjkb/bark) | Implements the Materialized Path pattern that allows you to easily create and interact with tree structures in Prisma | | [`prisma-cursorstream`](https://github.com/etabits/prisma-cursorstream) | Adds cursor-based streaming | | [`prisma-gpt`](https://github.com/aliyeysides/prisma-gpt) | Lets you query your database using natural language | | [`prisma-extension-caching`](https://github.com/isaev-the-poetry/prisma-extension-caching) | Adds the ability to cache complex queries | | [`prisma-extension-cache-manager`](https://github.com/random42/prisma-extension-cache-manager) | Caches model queries with any [cache-manager](https://www.npmjs.com/package/cache-manager) compatible cache | | [`prisma-extension-random`](https://github.com/nkeil/prisma-extension-random) | Lets you query for random rows in your database | | [`prisma-paginate`](https://github.com/sandrewTx08/prisma-paginate) | Adds support for paginating read queries | | [`prisma-extension-streamdal`](https://github.com/streamdal/prisma-extension-streamdal) | Adds support for Code-Native data pipelines using Streamdal | | [`prisma-rbac`](https://github.com/multipliedtwice/prisma-rbac) | Adds customizable role-based access control | | [`prisma-extension-redis`](https://github.com/yxx4c/prisma-extension-redis) | Extensive Prisma extension designed for efficient caching and cache invalidation using Redis and Dragonfly Databases | | [`prisma-cache-extension`](https://github.com/Shikhar97/prisma-cache) | Prisma extension for caching and invalidating cache with Redis(other Storage options to be supported) | | [`prisma-extension-casl`](https://github.com/dennemark/prisma-extension-casl) | Prisma client extension that utilizes CASL to enforce authorization logic on most simple and nested queries. | If you have built an extension and would like to see it featured, feel free to add it to the list by opening a pull request. ## Examples :::info The following example extensions are provided as examples only, and without warranty. They are supposed to show how Prisma Client extensions can be created using approaches documented here. We recommend using these examples as a source of inspiration for building your own extensions. ::: | Example | Description | | :------------------------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------ | | [`audit-log-context`](https://github.com/prisma/prisma-client-extensions/tree/main/audit-log-context) | Provides the current user's ID as context to Postgres audit log triggers | | [`callback-free-itx`](https://github.com/prisma/prisma-client-extensions/tree/main/callback-free-itx) | Adds a method to start interactive transactions without callbacks | | [`computed-fields`](https://github.com/prisma/prisma-client-extensions/tree/main/computed-fields) | Adds virtual / computed fields to result objects | | [`input-transformation`](https://github.com/prisma/prisma-client-extensions/tree/main/input-transformation) | Transforms the input arguments passed to Prisma Client queries to filter the result set | | [`input-validation`](https://github.com/prisma/prisma-client-extensions/tree/main/input-validation) | Runs custom validation logic on input arguments passed to mutation methods | | [`instance-methods`](https://github.com/prisma/prisma-client-extensions/tree/main/instance-methods) | Adds Active Record-like methods like `save()` and `delete()` to result objects | | [`json-field-types`](https://github.com/prisma/prisma-client-extensions/tree/main/json-field-types) | Uses strongly-typed runtime parsing for data stored in JSON columns | | [`model-filters`](https://github.com/prisma/prisma-client-extensions/tree/main/model-filters) | Adds reusable filters that can composed into complex `where` conditions for a model | | [`obfuscated-fields`](https://github.com/prisma/prisma-client-extensions/tree/main/obfuscated-fields) | Prevents sensitive data (e.g. `password` fields) from being included in results | | [`query-logging`](https://github.com/prisma/prisma-client-extensions/tree/main/query-logging) | Wraps Prisma Client queries with simple query timing and logging | | [`readonly-client`](https://github.com/prisma/prisma-client-extensions/tree/main/readonly-client) | Creates a client that only allows read operations | | [`retry-transactions`](https://github.com/prisma/prisma-client-extensions/tree/main/retry-transactions) | Adds a retry mechanism to transactions with exponential backoff and jitter | | [`row-level-security`](https://github.com/prisma/prisma-client-extensions/tree/main/row-level-security) | Uses Postgres row-level security policies to isolate data a multi-tenant application | | [`static-methods`](https://github.com/prisma/prisma-client-extensions/tree/main/static-methods) | Adds custom query methods to Prisma Client models | | [`transformed-fields`](https://github.com/prisma/prisma-client-extensions/tree/main/transformed-fields) | Demonstrates how to use result extensions to transform query results and add i18n to an app | | [`exists-method`](https://github.com/prisma/prisma-client-extensions/tree/main/exists-fn) | Demonstrates how to add an `exists` method to all your models | | [`update-delete-ignore-not-found `](https://github.com/prisma/prisma-client-extensions/tree/main/update-delete-ignore-not-found) | Demonstrates how to add the `updateIgnoreOnNotFound` and `deleteIgnoreOnNotFound` methods to all your models. | ## Going further - Learn more about [Prisma Client extensions](/orm/prisma-client/client-extensions). --- # Middleware sample: soft delete URL: https://www.prisma.io/docs/orm/prisma-client/client-extensions/middleware/soft-delete-middleware The following sample uses [middleware](/orm/prisma-client/client-extensions/middleware) to perform a **soft delete**. Soft delete means that a record is **marked as deleted** by changing a field like `deleted` to `true` rather than actually being removed from the database. Reasons to use a soft delete include: - Regulatory requirements that mean you have to keep data for a certain amount of time - 'Trash' / 'bin' functionality that allows users to restore content that was deleted **Note:** This page demonstrates a sample use of middleware. We do not intend the sample to be a fully functional soft delete feature and it does not cover all edge cases. For example, the middleware does not work with nested writes and therefore won't capture situations where you use `delete` or `deleteMany` as an option e.g. in an `update` query. This sample uses the following schema - note the `deleted` field on the `Post` model: ```prisma highlight=28;normal datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model User { id Int @id @default(autoincrement()) name String? email String @unique posts Post[] followers User[] @relation("UserToUser") user User? @relation("UserToUser", fields: [userId], references: [id]) userId Int? } model Post { id Int @id @default(autoincrement()) title String content String? user User? @relation(fields: [userId], references: [id]) userId Int? tags Tag[] views Int @default(0) //highlight-next-line deleted Boolean @default(false) } model Category { id Int @id @default(autoincrement()) parentCategory Category? @relation("CategoryToCategory", fields: [categoryId], references: [id]) category Category[] @relation("CategoryToCategory") categoryId Int? } model Tag { tagName String @id // Must be unique posts Post[] } ``` ## Step 1: Store status of record Add a field named `deleted` to the `Post` model. You can choose between two field types depending on your requirements: - `Boolean` with a default value of `false`: ```prisma highlight=4;normal model Post { id Int @id @default(autoincrement()) ... //highlight-next-line deleted Boolean @default(false) } ``` - Create a nullable `DateTime` field so that you know exactly _when_ a record was marked as deleted - `NULL` indicates that a record has not been deleted. In some cases, storing when a record was removed may be a regulatory requirement: ```prisma highlight=4;normal model Post { id Int @id @default(autoincrement()) ... //highlight-next-line deleted DateTime? } ``` > **Note**: Using two separate fields (`isDeleted` and `deletedDate`) may result in these two fields becoming out of sync - for example, a record may be marked as deleted but have no associated date.) This sample uses a `Boolean` field type for simplicity. ## Step 2: Soft delete middleware Add a middleware that performs the following tasks: - Intercepts `delete()` and `deleteMany()` queries for the `Post` model - Changes the `params.action` to `update` and `updateMany` respectively - Introduces a `data` argument and sets `{ deleted: true }`, preserving other filter arguments if they exist Run the following sample to test the soft delete middleware: ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient({}) async function main() { /***********************************/ /* SOFT DELETE MIDDLEWARE */ /***********************************/ prisma.$use(async (params, next) => { // Check incoming query type if (params.model == 'Post') { if (params.action == 'delete') { // Delete queries // Change action to an update params.action = 'update' params.args['data'] = { deleted: true } } if (params.action == 'deleteMany') { // Delete many queries params.action = 'updateMany' if (params.args.data != undefined) { params.args.data['deleted'] = true } else { params.args['data'] = { deleted: true } } } } return next(params) }) /***********************************/ /* TEST */ /***********************************/ const titles = [ { title: 'How to create soft delete middleware' }, { title: 'How to install Prisma' }, { title: 'How to update a record' }, ] console.log('\u001b[1;34mSTARTING SOFT DELETE TEST \u001b[0m') console.log('\u001b[1;34m#################################### \u001b[0m') let i = 0 let posts = new Array() // Create 3 new posts with a randomly assigned title each time for (i == 0; i < 3; i++) { const createPostOperation = prisma.post.create({ data: titles[Math.floor(Math.random() * titles.length)], }) posts.push(createPostOperation) } var postsCreated = await prisma.$transaction(posts) console.log( 'Posts created with IDs: ' + '\u001b[1;32m' + postsCreated.map((x) => x.id) + '\u001b[0m' ) // Delete the first post from the array const deletePost = await prisma.post.delete({ where: { id: postsCreated[0].id, // Random ID }, }) // Delete the 2nd two posts const deleteManyPosts = await prisma.post.deleteMany({ where: { id: { in: [postsCreated[1].id, postsCreated[2].id], }, }, }) const getPosts = await prisma.post.findMany({ where: { id: { in: postsCreated.map((x) => x.id), }, }, }) console.log() console.log( 'Deleted post with ID: ' + '\u001b[1;32m' + deletePost.id + '\u001b[0m' ) console.log( 'Deleted posts with IDs: ' + '\u001b[1;32m' + [postsCreated[1].id + ',' + postsCreated[2].id] + '\u001b[0m' ) console.log() console.log( 'Are the posts still available?: ' + (getPosts.length == 3 ? '\u001b[1;32m' + 'Yes!' + '\u001b[0m' : '\u001b[1;31m' + 'No!' + '\u001b[0m') ) console.log() console.log('\u001b[1;34m#################################### \u001b[0m') // 4. Count ALL posts const f = await prisma.post.findMany({}) console.log('Number of posts: ' + '\u001b[1;32m' + f.length + '\u001b[0m') // 5. Count DELETED posts const r = await prisma.post.findMany({ where: { deleted: true, }, }) console.log( 'Number of SOFT deleted posts: ' + '\u001b[1;32m' + r.length + '\u001b[0m' ) } main() ``` The sample outputs the following: ```no-lines STARTING SOFT DELETE TEST #################################### Posts created with IDs: 587,588,589 Deleted post with ID: 587 Deleted posts with IDs: 588,589 Are the posts still available?: Yes! #################################### ``` :::tip Comment out the middleware to see the message change. ::: ✔ Pros of this approach to soft delete include: - Soft delete happens at data access level, which means that you cannot delete records unless you use raw SQL ✘ Cons of this approach to soft delete include: - Content can still be read and updated unless you explicitly filter by `where: { deleted: false }` - in a large project with a lot of queries, there is a risk that soft deleted content will still be displayed - You can still use raw SQL to delete records :::tip You can create rules or triggers ([MySQL](https://dev.mysql.com/doc/refman/8.0/en/trigger-syntax.html) and [PostgreSQL](https://www.postgresql.org/docs/8.1/rules-update.html)) at a database level to prevent records from being deleted. ::: ## Step 3: Optionally prevent read/update of soft deleted records In step 2, we implemented middleware that prevents `Post` records from being deleted. However, you can still read and update deleted records. This step explores two ways to prevent the reading and updating of deleted records. > **Note**: These options are just ideas with pros and cons, you may choose to do something entirely different. ### Option 1: Implement filters in your own application code In this option: - Prisma Client middleware is responsible for preventing records from being deleted - Your own application code (which could be a GraphQL API, a REST API, a module) is responsible for filtering out deleted posts where necessary (`{ where: { deleted: false } }`) when reading and updating data - for example, the `getPost` GraphQL resolver never returns a deleted post ✔ Pros of this approach to soft delete include: - No change to Prisma Client's create/update queries - you can easily request deleted records if you need them - Modifying queries in middleware can have some unintended consequences, such as changing query return types (see option 2) ✘ Cons of this approach to soft delete include: - Logic relating to soft delete maintained in two different places - If your API surface is very large and maintained by multiple contributors, it may be difficult to enforce certain business rules (for example, never allow deleted records to be updated) ### Option 2: Use middleware to determine the behavior of read/update queries for deleted records Option two uses Prisma Client middleware to prevent soft deleted records from being returned. The following table describes how the middleware affects each query: | **Query** | **Middleware logic** | **Changes to return type** | | :------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------------------------------- | | `findUnique()` | 🔧 Change query to `findFirst` (because you cannot apply `deleted: false` filters to `findUnique()`)
🔧 Add `where: { deleted: false }` filter to exclude soft deleted posts
🔧 From version 5.0.0, you can use `findUnique()` to apply `delete: false` filters since [non unique fields are exposed](/orm/reference/prisma-client-reference#filter-on-non-unique-fields-with-userwhereuniqueinput). | No change | | | `findMany` | 🔧 Add `where: { deleted: false }` filter to exclude soft deleted posts by default
🔧 Allow developers to **explicitly request** soft deleted posts by specifying `deleted: true` | No change | | `update` | 🔧 Change query to `updateMany` (because you cannot apply `deleted: false` filters to `update`)
🔧 Add `where: { deleted: false }` filter to exclude soft deleted posts | `{ count: n }` instead of `Post` | | `updateMany` | 🔧 Add `where: { deleted: false }` filter to exclude soft deleted posts | No change | - **Is it not possible to utilize soft delete with `findFirstOrThrow()` or `findUniqueOrThrow()`?**
From version [5.1.0](https://github.com/prisma/prisma/releases/5.1.0), you can apply soft delete `findFirstOrThrow()` or `findUniqueOrThrow()` by using middleware. - **Why are you making it possible to use `findMany()` with a `{ where: { deleted: true } }` filter, but not `updateMany()`?**
This particular sample was written to support the scenario where a user can _restore_ their deleted blog post (which requires a list of soft deleted posts) - but the user should not be able to edit a deleted post. - **Can I still `connect` or `connectOrCreate` a deleted post?**
In this sample - yes. The middleware does not prevent you from connecting an existing, soft deleted post to a user. Run the following sample to see how middleware affects each query: ```ts import { PrismaClient, Prisma } from '@prisma/client' const prisma = new PrismaClient({}) async function main() { /***********************************/ /* SOFT DELETE MIDDLEWARE */ /***********************************/ prisma.$use(async (params, next) => { if (params.model == 'Post') { if (params.action === 'findUnique' || params.action === 'findFirst') { // Change to findFirst - you cannot filter // by anything except ID / unique with findUnique() params.action = 'findFirst' // Add 'deleted' filter // ID filter maintained params.args.where['deleted'] = false } if ( params.action === 'findFirstOrThrow' || params.action === 'findUniqueOrThrow' ) { if (params.args.where) { if (params.args.where.deleted == undefined) { // Exclude deleted records if they have not been explicitly requested params.args.where['deleted'] = false } } else { params.args['where'] = { deleted: false } } } if (params.action === 'findMany') { // Find many queries if (params.args.where) { if (params.args.where.deleted == undefined) { params.args.where['deleted'] = false } } else { params.args['where'] = { deleted: false } } } } return next(params) }) prisma.$use(async (params, next) => { if (params.model == 'Post') { if (params.action == 'update') { // Change to updateMany - you cannot filter // by anything except ID / unique with findUnique() params.action = 'updateMany' // Add 'deleted' filter // ID filter maintained params.args.where['deleted'] = false } if (params.action == 'updateMany') { if (params.args.where != undefined) { params.args.where['deleted'] = false } else { params.args['where'] = { deleted: false } } } } return next(params) }) prisma.$use(async (params, next) => { // Check incoming query type if (params.model == 'Post') { if (params.action == 'delete') { // Delete queries // Change action to an update params.action = 'update' params.args['data'] = { deleted: true } } if (params.action == 'deleteMany') { // Delete many queries params.action = 'updateMany' if (params.args.data != undefined) { params.args.data['deleted'] = true } else { params.args['data'] = { deleted: true } } } } return next(params) }) /***********************************/ /* TEST */ /***********************************/ const titles = [ { title: 'How to create soft delete middleware' }, { title: 'How to install Prisma' }, { title: 'How to update a record' }, ] console.log('\u001b[1;34mSTARTING SOFT DELETE TEST \u001b[0m') console.log('\u001b[1;34m#################################### \u001b[0m') let i = 0 let posts = new Array() // Create 3 new posts with a randomly assigned title each time for (i == 0; i < 3; i++) { const createPostOperation = prisma.post.create({ data: titles[Math.floor(Math.random() * titles.length)], }) posts.push(createPostOperation) } var postsCreated = await prisma.$transaction(posts) console.log( 'Posts created with IDs: ' + '\u001b[1;32m' + postsCreated.map((x) => x.id) + '\u001b[0m' ) // Delete the first post from the array const deletePost = await prisma.post.delete({ where: { id: postsCreated[0].id, // Random ID }, }) // Delete the 2nd two posts const deleteManyPosts = await prisma.post.deleteMany({ where: { id: { in: [postsCreated[1].id, postsCreated[2].id], }, }, }) const getOnePost = await prisma.post.findUnique({ where: { id: postsCreated[0].id, }, }) const getOneUniquePostOrThrow = async () => await prisma.post.findUniqueOrThrow({ where: { id: postsCreated[0].id, }, }) const getOneFirstPostOrThrow = async () => await prisma.post.findFirstOrThrow({ where: { id: postsCreated[0].id, }, }) const getPosts = await prisma.post.findMany({ where: { id: { in: postsCreated.map((x) => x.id), }, }, }) const getPostsAnDeletedPosts = await prisma.post.findMany({ where: { id: { in: postsCreated.map((x) => x.id), }, deleted: true, }, }) const updatePost = await prisma.post.update({ where: { id: postsCreated[1].id, }, data: { title: 'This is an updated title (update)', }, }) const updateManyDeletedPosts = await prisma.post.updateMany({ where: { deleted: true, id: { in: postsCreated.map((x) => x.id), }, }, data: { title: 'This is an updated title (updateMany)', }, }) console.log() console.log( 'Deleted post (delete) with ID: ' + '\u001b[1;32m' + deletePost.id + '\u001b[0m' ) console.log( 'Deleted posts (deleteMany) with IDs: ' + '\u001b[1;32m' + [postsCreated[1].id + ',' + postsCreated[2].id] + '\u001b[0m' ) console.log() console.log( 'findUnique: ' + (getOnePost?.id != undefined ? '\u001b[1;32m' + 'Posts returned!' + '\u001b[0m' : '\u001b[1;31m' + 'Post not returned!' + '(Value is: ' + JSON.stringify(getOnePost) + ')' + '\u001b[0m') ) try { console.log('findUniqueOrThrow: ') await getOneUniquePostOrThrow() } catch (error) { if ( error instanceof Prisma.PrismaClientKnownRequestError && error.code == 'P2025' ) console.log( '\u001b[1;31m' + 'PrismaClientKnownRequestError is catched' + '(Error name: ' + error.name + ')' + '\u001b[0m' ) } try { console.log('findFirstOrThrow: ') await getOneFirstPostOrThrow() } catch (error) { if ( error instanceof Prisma.PrismaClientKnownRequestError && error.code == 'P2025' ) console.log( '\u001b[1;31m' + 'PrismaClientKnownRequestError is catched' + '(Error name: ' + error.name + ')' + '\u001b[0m' ) } console.log() console.log( 'findMany: ' + (getPosts.length == 3 ? '\u001b[1;32m' + 'Posts returned!' + '\u001b[0m' : '\u001b[1;31m' + 'Posts not returned!' + '\u001b[0m') ) console.log( 'findMany ( delete: true ): ' + (getPostsAnDeletedPosts.length == 3 ? '\u001b[1;32m' + 'Posts returned!' + '\u001b[0m' : '\u001b[1;31m' + 'Posts not returned!' + '\u001b[0m') ) console.log() console.log( 'update: ' + (updatePost.id != undefined ? '\u001b[1;32m' + 'Post updated!' + '\u001b[0m' : '\u001b[1;31m' + 'Post not updated!' + '(Value is: ' + JSON.stringify(updatePost) + ')' + '\u001b[0m') ) console.log( 'updateMany ( delete: true ): ' + (updateManyDeletedPosts.count == 3 ? '\u001b[1;32m' + 'Posts updated!' + '\u001b[0m' : '\u001b[1;31m' + 'Posts not updated!' + '\u001b[0m') ) console.log() console.log('\u001b[1;34m#################################### \u001b[0m') // 4. Count ALL posts const f = await prisma.post.findMany({}) console.log( 'Number of active posts: ' + '\u001b[1;32m' + f.length + '\u001b[0m' ) // 5. Count DELETED posts const r = await prisma.post.findMany({ where: { deleted: true, }, }) console.log( 'Number of SOFT deleted posts: ' + '\u001b[1;32m' + r.length + '\u001b[0m' ) } main() ``` The sample outputs the following: ``` STARTING SOFT DELETE TEST #################################### Posts created with IDs: 680,681,682 Deleted post (delete) with ID: 680 Deleted posts (deleteMany) with IDs: 681,682 findUnique: Post not returned!(Value is: []) findMany: Posts not returned! findMany ( delete: true ): Posts returned! update: Post not updated!(Value is: {"count":0}) updateMany ( delete: true ): Posts not updated! #################################### Number of active posts: 0 Number of SOFT deleted posts: 95 ``` ✔ Pros of this approach: - A developer can make a conscious choice to include deleted records in `findMany` - You cannot accidentally read or update a deleted record ✖ Cons of this approach: - Not obvious from API that you aren't getting all records and that `{ where: { deleted: false } }` is part of the default query - Return type `update` affected because middleware changes the query to `updateMany` - Doesn't handle complex queries with `AND`, `OR`, `every`, etc... - Doesn't handle filtering when using `include` from another model. ## FAQ ### Can I add a global `includeDeleted` to the `Post` model? You may be tempted to 'hack' your API by adding a `includeDeleted` property to the `Post` model and make the following query possible: ```ts prisma.post.findMany({ where: { includeDeleted: true } }) ``` > **Note**: You would still need to write middleware. We **✘ do not** recommend this approach as it pollutes the schema with fields that do not represent real data. --- # Middleware sample: logging URL: https://www.prisma.io/docs/orm/prisma-client/client-extensions/middleware/logging-middleware The following example logs the time taken for a Prisma Client query to run: ```ts const prisma = new PrismaClient() prisma.$use(async (params, next) => { const before = Date.now() const result = await next(params) const after = Date.now() console.log(`Query ${params.model}.${params.action} took ${after - before}ms`) return result }) const create = await prisma.post.create({ data: { title: 'Welcome to Prisma Day 2020', }, }) const createAgain = await prisma.post.create({ data: { title: 'All about database collation', }, }) ``` Example output: ```no-lines Query Post.create took 92ms Query Post.create took 15ms ``` The example is based on the following sample schema: ```prisma generator client { provider = "prisma-client-js" } datasource db { provider = "mysql" url = env("DATABASE_URL") } model Post { authorId Int? content String? id Int @id @default(autoincrement()) published Boolean @default(false) title String user User? @relation(fields: [authorId], references: [id]) language String? @@index([authorId], name: "authorId") } model User { email String @unique id Int @id @default(autoincrement()) name String? posts Post[] extendedProfile Json? role Role @default(USER) } enum Role { ADMIN USER MODERATOR } ``` ## Going further You can also use [Prisma Client extensions](/orm/prisma-client/client-extensions) to log the time it takes to perform a query. A functional example can be found in [this GitHub repository](https://github.com/prisma/prisma-client-extensions/tree/main/query-logging). --- # Middleware sample: session data URL: https://www.prisma.io/docs/orm/prisma-client/client-extensions/middleware/session-data-middleware The following example sets the `language` field of each `Post` to the context language (taken, for example, from session state): ```ts const prisma = new PrismaClient() const contextLanguage = 'en-us' // Session state prisma.$use(async (params, next) => { if (params.model == 'Post' && params.action == 'create') { params.args.data.language = contextLanguage } return next(params) }) const create = await prisma.post.create({ data: { title: 'My post in English', }, }) ``` The example is based on the following sample schema: ```prisma generator client { provider = "prisma-client-js" } datasource db { provider = "mysql" url = env("DATABASE_URL") } model Post { authorId Int? content String? id Int @id @default(autoincrement()) published Boolean @default(false) title String user User? @relation(fields: [authorId], references: [id]) language String? @@index([authorId], name: "authorId") } model User { email String @unique id Int @id @default(autoincrement()) name String? posts Post[] extendedProfile Json? role Role @default(USER) } enum Role { ADMIN USER MODERATOR } ``` --- # Middleware URL: https://www.prisma.io/docs/orm/prisma-client/client-extensions/middleware/index **Deprecated**: Middleware is deprecated in version 4.16.0. We recommend using the [Prisma Client extensions `query` component type](/orm/prisma-client/client-extensions/query) as an alternative to middleware. Prisma Client extensions were first introduced into Preview in version 4.7.0 and made Generally Available in 4.16.0. Prisma Client extensions allow you to create independent Prisma Client instances and bind each client to a specific filter or user. For example, you could bind clients to specific users to provide user isolation. Prisma Client extensions also provide end-to-end type safety. Middlewares act as query-level lifecycle hooks, which allow you to perform an action before or after a query runs. Use the [`prisma.$use`](/orm/reference/prisma-client-reference#use) method to add middleware, as follows: ```ts highlight=4-9,12-17;normal const prisma = new PrismaClient() // Middleware 1 //highlight-start prisma.$use(async (params, next) => { // Manipulate params here const result = await next(params) // See results here return result }) //highlight-end // Middleware 2 //highlight-start prisma.$use(async (params, next) => { // Manipulate params here const result = await next(params) // See results here return result }) //highlight-end // Queries here ``` Do not invoke `next` multiple times within a middleware when using [batch transactions](/orm/prisma-client/queries/transactions#sequential-prisma-client-operations). This will cause you to break out of the transaction and lead to unexpected results. [`params`](/orm/reference/prisma-client-reference#params) represent parameters available in the middleware, such as the name of the query, and [`next`](/orm/reference/prisma-client-reference#next) represents [the next middleware in the stack _or_ the original Prisma Client query](#running-order-and-the-middleware-stack). Possible use cases for middleware include: - Setting or overwriting a field value - for example, [setting the context language of a blog post comment](/orm/prisma-client/client-extensions/middleware/session-data-middleware) - Validating input data - for example, check user input for inappropriate language via an external service - Intercept a `delete` query and change it to an `update` in order to perform a [soft delete](/orm/prisma-client/client-extensions/middleware/soft-delete-middleware) - [Log the time taken to perform a query](/orm/prisma-client/client-extensions/middleware/logging-middleware) There are many more use cases for middleware - this list serves as inspiration for the types of problems that middleware is designed to address. ## Samples The following sample scenarios show how to use middleware in practice: ## Where to add middleware Add Prisma Client middleware **outside the context of the request handler**, otherwise each request adds a new _instance_ of the middleware to the stack. The following example demonstrates where to add Prisma Client middleware in the context of an Express app: ```ts highlight=6-11;normal import express from 'express' import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() //highlight-start prisma.$use(async (params, next) => { // Manipulate params here const result = await next(params) // See results here return result }) //highlight-end const app = express() app.get('/feed', async (req, res) => { // NO MIDDLEWARE HERE const posts = await prisma.post.findMany({ where: { published: true }, include: { author: true }, }) res.json(posts) }) ``` ## Running order and the middleware stack If you have multiple middlewares, the running order for **each separate query** is: 1. All logic **before** `await next(params)` in each middleware, in descending order 2. All logic **after** `await next(params)` in each middleware, in ascending order Depending on where you are in the stack, `await next(params)` either: - Runs the next middleware (in middlewares #1 and #2 in the example) _or_ - Runs the original Prisma Client query (in middleware #3) ```ts const prisma = new PrismaClient() // Middleware 1 prisma.$use(async (params, next) => { console.log(params.args.data.title) console.log('1') const result = await next(params) console.log('6') return result }) // Middleware 2 prisma.$use(async (params, next) => { console.log('2') const result = await next(params) console.log('5') return result }) // Middleware 3 prisma.$use(async (params, next) => { console.log('3') const result = await next(params) console.log('4') return result }) const create = await prisma.post.create({ data: { title: 'Welcome to Prisma Day 2020', }, }) const create2 = await prisma.post.create({ data: { title: 'How to Prisma!', }, }) ``` Output: ```no-lines Welcome to Prisma Day 2020 1 2 3 4 5 6 How to Prisma! 1 2 3 4 5 6 ``` ## Performance and appropriate use cases Middleware executes for **every** query, which means that overuse has the potential to negatively impact performance. To avoid adding performance overheads: - Check the `params.model` and `params.action` properties early in your middleware to avoid running logic unnecessarily: ```ts prisma.$use(async (params, next) => { if (params.model == 'Post' && params.action == 'delete') { // Logic only runs for delete action and Post model } return next(params) }) ``` - Consider whether middleware is the appropriate solution for your scenario. For example: - If you need to populate a field, can you use the [`@default`](/orm/reference/prisma-schema-reference#default) attribute? - If you need to set the value of a `DateTime` field, can you use the `now()` function or the `@updatedAt` attribute? - If you need to perform more complex validation, can you use a `CHECK` constraint in the database itself? --- # Extensions URL: https://www.prisma.io/docs/orm/prisma-client/client-extensions/index Prisma Client extensions are Generally Available from versions 4.16.0 and later. They were introduced in Preview in version 4.7.0. Make sure you enable the `clientExtensions` Preview feature flag if you are running on a version earlier than 4.16.0. You can use Prisma Client extensions to add functionality to your models, result objects, and queries, or to add client-level methods. You can create an extension with one or more of the following component types: - `model`: [add custom methods or fields to your models](/orm/prisma-client/client-extensions/model) - `client`: [add client-level methods to Prisma Client](/orm/prisma-client/client-extensions/client) - `query`: [create custom Prisma Client queries](/orm/prisma-client/client-extensions/query) - `result`: [add custom fields to your query results](/orm/prisma-client/client-extensions/result) For example, you might create an extension that uses the `model` and `client` component types. ## About Prisma Client extensions When you use a Prisma Client extension, you create an _extended client_. An extended client is a lightweight variant of the standard Prisma Client that is wrapped by one or more extensions. The standard client is not mutated. You can add as many extended clients as you want to your project. [Learn more about extended clients](#extended-clients). You can associate a single extension, or multiple extensions, with an extended client. [Learn more about multiple extensions](#multiple-extensions). You can [share your Prisma Client extensions](/orm/prisma-client/client-extensions/shared-extensions) with other Prisma ORM users, and [import Prisma Client extensions developed by other users](/orm/prisma-client/client-extensions/shared-extensions#install-a-shared-packaged-extension) into your Prisma ORM project. ### Extended clients Extended clients interact with each other, and with the standard client, as follows: - Each extended client operates independently in an isolated instance. - Extended clients cannot conflict with each other, or with the standard client. - All extended clients and the standard client communicate with the same [Prisma ORM query engine](/orm/more/under-the-hood/engines). - All extended clients and the standard client share the same connection pool. > **Note**: The author of an extension can modify this behavior since they're able to run arbitrary code as part of an extension. For example, an extension might actually create an entirely new `PrismaClient` instance (including its own query engine and connection pool). Be sure to check the documentation of the extension you're using to learn about any specific behavior it might implement. ### Example use cases for extended clients Because extended clients operate in isolated instances, they can be a good way to do the following, for example: - Implement row-level security (RLS), where each HTTP request has its own client with its own RLS extension, customized with session data. This can keep each user entirely separate, each in a separate client. - Add a `user.current()` method for the `User` model to get the currently logged-in user. - Enable more verbose logging for requests if a debug cookie is set. - Attach a unique request id to all logs so that you can correlate them later, for example to help you analyze the operations that Prisma Client carries out. - Remove a `delete` method from models unless the application calls the admin endpoint and the user has the necessary privileges. ## Add an extension to Prisma Client You can create an extension using two primary ways: - Use the client-level [`$extends`](/orm/reference/prisma-client-reference#client-methods) method ```ts const prisma = new PrismaClient().$extends({ name: 'signUp', // Optional: name appears in error logs model: { // This is a `model` component user: { ... } // The extension logic for the `user` model goes inside the curly braces }, }) ``` - Use the `Prisma.defineExtension` method to define an extension and assign it to a variable, and then pass the extension to the client-level `$extends` method ```ts import { Prisma } from '@prisma/client' // Define the extension const myExtension = Prisma.defineExtension({ name: 'signUp', // Optional: name appears in error logs model: { // This is a `model` component user: { ... } // The extension logic for the `user` model goes inside the curly braces }, }) // Pass the extension to a Prisma Client instance const prisma = new PrismaClient().$extends(myExtension) ``` :::tip This pattern is useful for when you would like to separate extensions into multiple files or directories within a project. ::: The above examples use the [`model` extension component](/orm/prisma-client/client-extensions/model) to extend the `User` model. In your `$extends` method, use the appropriate extension component or components ([`model`](/orm/prisma-client/client-extensions/model), [`client`](/orm/prisma-client/client-extensions/client), [`result`](/orm/prisma-client/client-extensions/result) or [`query`](/orm/prisma-client/client-extensions/query)). ## Name an extension for error logs You can name your extensions to help identify them in error logs. To do so, use the optional field `name`. For example: ```ts const prisma = new PrismaClient().$extends({ name: `signUp`, // (Optional) Extension name model: { user: { ... } }, }) ``` ## Multiple extensions You can associate an extension with an [extended client](#about-prisma-client-extensions) in one of two ways: - You can associate it with an extended client on its own, or - You can combine the extension with other extensions and associate all of these extensions with an extended client. The functionality from these combined extensions applies to the same extended client. Note: [Combined extensions can conflict](#conflicts-in-combined-extensions). You can combine the two approaches above. For example, you might associate one extension with its own extended client and associate two other extensions with another extended client. [Learn more about how client instances interact](#extended-clients). ### Apply multiple extensions to an extended client In the following example, suppose that you have two extensions, `extensionA` and `extensionB`. There are two ways to combine these. #### Option 1: Declare the new client in one line With this option, you apply both extensions to a new client in one line of code. ```ts // First of all, store your original Prisma Client in a variable as usual const prisma = new PrismaClient() // Declare an extended client that has an extensionA and extensionB const prismaAB = prisma.$extends(extensionA).$extends(extensionB) ``` You can then refer to `prismaAB` in your code, for example `prismaAB.myExtensionMethod()`. #### Option 2: Declare multiple extended clients The advantage of this option is that you can call any of the extended clients separately. ```ts // First of all, store your original Prisma Client in a variable as usual const prisma = new PrismaClient() // Declare an extended client that has extensionA applied const prismaA = prisma.$extends(extensionA) // Declare an extended client that has extensionB applied const prismaB = prisma.$extends(extensionB) // Declare an extended client that is a combination of clientA and clientB const prismaAB = prismaA.$extends(extensionB) ``` In your code, you can call any of these clients separately, for example `prismaA.myExtensionMethod()`, `prismaB.myExtensionMethod()`, or `prismaAB.myExtensionMethod()`. ### Conflicts in combined extensions When you combine two or more extensions into a single extended client, then the _last_ extension that you declare takes precedence in any conflict. In the example in option 1 above, suppose there is a method called `myExtensionMethod()` defined in `extensionA` and a method called `myExtensionMethod()` in `extensionB`. When you call `prismaAB.myExtensionMethod()`, then Prisma Client uses `myExtensionMethod()` as defined in `extensionB`. ## Type of an extended client You can infer the type of an extended Prisma Client instance using the [`typeof`](https://www.typescriptlang.org/docs/handbook/2/typeof-types.html) utility as follows: ```ts const extendedPrismaClient = new PrismaClient().$extends({ /** extension */ }) type ExtendedPrismaClient = typeof extendedPrismaClient ``` If you're using Prisma Client as a singleton, you can get the type of the extended Prisma Client instance using the `typeof` and [`ReturnType`](https://www.typescriptlang.org/docs/handbook/utility-types.html#returntypetype) utilities as follows: ```ts function getExtendedClient() { return new PrismaClient().$extends({ /* extension */ }) } type ExtendedPrismaClient = ReturnType ``` ## Extending model types with `Prisma.Result` You can use the `Prisma.Result` type utility to extend model types to include properties added via client extensions. This allows you to infer the type of the extended model, including the extended properties. ### Example The following example demonstrates how to use `Prisma.Result` to extend the `User` model type to include a `__typename` property added via a client extension. ```ts import { PrismaClient, Prisma } from '@prisma/client' const prisma = new PrismaClient().$extends({ result: { user: { __typename: { needs: {}, compute() { return 'User' }, }, }, }, }) type ExtendedUser = Prisma.Result async function main() { const user: ExtendedUser = await prisma.user.findFirstOrThrow({ select: { id: true, __typename: true, }, }) console.log(user.__typename) // Output: 'User' } main() ``` The `Prisma.Result` type utility is used to infer the type of the extended `User` model, including the `__typename` property added via the client extension. ## Limitations ### Usage of `$on` and `$use` with extended clients `$on` and `$use` are not available in extended clients. If you would like to continue using these [client-level methods](/orm/reference/prisma-client-reference#client-methods) with an extended client, you will need to hook them up before extending the client. ```ts const prisma = new PrismaClient() prisma.$use(async (params, next) => { console.log('This is middleware!') return next(params) }) const xPrisma = prisma.$extends({ name: 'myExtension', model: { user: { async signUp(email: string) { await prisma.user.create({ data: { email } }) }, }, }, }) ``` To learn more, see our documentation on [`$on`](/orm/reference/prisma-client-reference#on) and [`$use`](/orm/reference/prisma-client-reference#use) ### Usage of client-level methods in extended clients [Client-level methods](/orm/reference/prisma-client-reference#client-methods) do not necessarily exist on extended clients. For these clients you will need to first check for existence before using. ```ts const xPrisma = new PrismaClient().$extends(...); if (xPrisma.$connect) { xPrisma.$connect() } ``` ### Usage with nested operations The `query` extension type does not support nested read and write operations. --- # Prisma validator URL: https://www.prisma.io/docs/orm/prisma-client/type-safety/prisma-validator The [`Prisma.validator`](/orm/reference/prisma-client-reference#prismavalidator) is a utility function that takes a generated type and returns a type-safe object which adheres to the generated types model fields. This page introduces the `Prisma.validator` and offers some motivations behind why you might choose to use it. > **Note**: If you have a use case for `Prisma.validator`, be sure to check out this [blog post](https://www.prisma.io/blog/satisfies-operator-ur8ys8ccq7zb) about improving your Prisma Client workflows with the new TypeScript `satisfies` keyword. It's likely that you can solve your use case natively using `satisfies` instead of using `Prisma.validator`. ## Creating a typed query statement Let's imagine that you created a new `userEmail` object that you wanted to re-use in different queries throughout your application. It's typed and can be safely used in queries. The below example asks `Prisma` to return the `email` of the user whose `id` is 3, if no user exists it will return `null`. ```ts import { Prisma } from '@prisma/client' const userEmail: Prisma.UserSelect = { email: true, } // Run inside async function const user = await prisma.user.findUnique({ where: { id: 3, }, select: userEmail, }) ``` This works well but there is a caveat to extracting query statements this way. You'll notice that if you hover your mouse over `userEmail` TypeScript won't infer the object's key or value (that is, `email: true`). The same applies if you use dot notation on `userEmail` within the `prisma.user.findUnique(...)` query, you will be able to access all of the properties available to a `select` object. If you are using this in one file that may be fine, but if you are going to export this object and use it in other queries, or if you are compiling an external library where you want to control how the user uses this object within their queries then this won't be type-safe. The object `userEmail` has been created to select only the user's `email`, and yet it still gives access to all the other properties available. **It is typed, but not type-safe**. `Prisma` has a way to validate generated types to make sure they are type-safe, a utility function available on the namespace called `validator`. ## Using the `Prisma.validator` The following example passes the `UserSelect` generated type into the `Prisma.validator` utility function and defines the expected return type in much the same way as the previous example. ```ts highlight=3,4,5;delete|7-9;add import { Prisma } from '@prisma/client' //delete-start const userEmail: Prisma.UserSelect = { email: true, } //delete-end //add-start const userEmail = Prisma.validator()({ email: true, }) //add-end // Run inside async function const user = await prisma.user.findUnique({ where: { id: 3, }, select: userEmail, }) ``` Alternatively, you can use the following syntax that uses a "selector" pattern using an existing instance of Prisma Client: ```ts import { Prisma } from '@prisma/client' import prisma from './lib/prisma' const userEmail = Prisma.validator( prisma, 'user', 'findUnique', 'select' )({ email: true, }) ``` The big difference is that the `userEmail` object is now type-safe. If you hover your mouse over it TypeScript will tell you the object's key/value pair. If you use dot notation to access the object's properties you will only be able to access the `email` property of the object. This functionality is handy when combined with user defined input, like form data. ## Combining `Prisma.validator` with form input The following example creates a type-safe function from the `Prisma.validator` which can be used when interacting with user created data, such as form inputs. > **Note**: Form input is determined at runtime so can't be verified by only using TypeScript. Be sure to validate your form input through other means too (such as an external validation library) before passing that data through to your database. ```ts import { Prisma, PrismaClient } from '@prisma/client' const prisma = new PrismaClient() // Create a new function and pass the parameters onto the validator const createUserAndPost = ( name: string, email: string, postTitle: string, profileBio: string ) => { return Prisma.validator()({ name, email, posts: { create: { title: postTitle, }, }, profile: { create: { bio: profileBio, }, }, }) } const findSpecificUser = (email: string) => { return Prisma.validator()({ email, }) } // Create the user in the database based on form input // Run inside async function await prisma.user.create({ data: createUserAndPost( 'Rich', 'rich@boop.com', 'Life of Pie', 'Learning each day' ), }) // Find the specific user based on form input // Run inside async function const oneUser = await prisma.user.findUnique({ where: findSpecificUser('rich@boop.com'), }) ``` The `createUserAndPost` custom function is created using the `Prisma.validator` and passed a generated type, `UserCreateInput`. The `Prisma.validator` validates the functions input because the types assigned to the parameters must match those the generated type expects. --- # Operating against partial structures of your model types URL: https://www.prisma.io/docs/orm/prisma-client/type-safety/operating-against-partial-structures-of-model-types When using Prisma Client, every model from your [Prisma schema](/orm/prisma-schema) is translated into a dedicated TypeScript type. For example, assume you have the following `User` and `Post` models: ```prisma model User { id Int @id email String @unique name String? posts Post[] } model Post { id Int @id author User @relation(fields: [userId], references: [id]) title String published Boolean @default(false) userId Int } ``` The Prisma Client code that's generated from this schema contains this representation of the `User` type: ```ts export type User = { id: string email: string name: string | null } ``` ## Problem: Using variations of the generated model type ### Description In some scenarios, you may need a _variation_ of the generated `User` type. For example, when you have a function that expects an instance of the `User` model that carries the `posts` relation. Or when you need a type to pass only the `User` model's `email` and `name` fields around in your application code. ### Solution As a solution, you can customize the generated model type using Prisma Client's helper types. The `User` type only contains the model's [scalar](/orm/prisma-schema/data-model/models#scalar-fields) fields, but doesn't account for any relations. That's because [relations are not included by default](/orm/prisma-client/queries/select-fields#return-the-default-fields) in Prisma Client queries. However, sometimes it's useful to have a type available that **includes a relation** (i.e. a type that you'd get from an API call that uses [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields)). Similarly, another useful scenario could be to have a type available that **includes only a subset of the model's scalar fields** (i.e. a type that you'd get from an API call that uses [`select`](/orm/prisma-client/queries/select-fields#select-specific-fields)). One way of achieving this would be to define these types manually in your application code: ```ts // 1: Define a type that includes the relation to `Post` type UserWithPosts = { id: string email: string name: string | null posts: Post[] } // 2: Define a type that only contains a subset of the scalar fields type UserPersonalData = { email: string name: string | null } ``` While this is certainly feasible, this approach increases the maintenance burden upon changes to the Prisma schema as you need to manually maintain the types. A cleaner solution to this is to use the `UserGetPayload` type that is generated and exposed by Prisma Client under the `Prisma` namespace in combination with the [`validator`](/orm/prisma-client/type-safety/prisma-validator). The following example uses the `Prisma.validator` to create two type-safe objects and then uses the `Prisma.UserGetPayload` utility function to create a type that can be used to return all users and their posts. ```ts import { Prisma } from '@prisma/client' // 1: Define a type that includes the relation to `Post` const userWithPosts = Prisma.validator()({ include: { posts: true }, }) // 2: Define a type that only contains a subset of the scalar fields const userPersonalData = Prisma.validator()({ select: { email: true, name: true }, }) // 3: This type will include a user and all their posts type UserWithPosts = Prisma.UserGetPayload ``` The main benefits of the latter approach are: - Cleaner approach as it leverages Prisma Client's generated types - Reduced maintenance burden and improved type safety when the schema changes ## Problem: Getting access to the return type of a function ### Description When doing [`select`](/orm/reference/prisma-client-reference#select) or [`include`](/orm/reference/prisma-client-reference#include) operations on your models and returning these variants from a function, it can be difficult to gain access to the return type, e.g: ```ts // Function definition that returns a partial structure async function getUsersWithPosts() { const users = await prisma.user.findMany({ include: { posts: true } }) return users } ``` Extracting the type that represents "users with posts" from the above code snippet requires some advanced TypeScript usage: ```ts // Function definition that returns a partial structure async function getUsersWithPosts() { const users = await prisma.user.findMany({ include: { posts: true } }) return users } // Extract `UsersWithPosts` type with type ThenArg = T extends PromiseLike ? U : T type UsersWithPosts = ThenArg> // run inside `async` function const usersWithPosts: UsersWithPosts = await getUsersWithPosts() ``` ### Solution With the `PromiseReturnType` that is exposed by the `Prisma` namespace, you can solve this more elegantly: ```ts import { Prisma } from '@prisma/client' type UsersWithPosts = Prisma.PromiseReturnType ``` --- This guide introduces Prisma ORM's type system and explains how to introspect existing native types in your database, and how to use types when you apply schema changes to your database with Prisma Migrate or `db push`. ## How does Prisma ORM's type system work? Prisma ORM uses _types_ to define the kind of data that a field can hold. To make it easy to get started, Prisma ORM provides a small number of core [scalar types](/orm/reference/prisma-schema-reference#model-field-scalar-types) that should cover most default use cases. For example, take the following blog post model: ```prisma file=schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } model Post { id Int @id title String createdAt DateTime } ``` The `title` field of the `Post` model uses the `String` scalar type, while the `createdAt` field uses the `DateTime` scalar type. Databases also have their own type system, which defines the type of value that a column can hold. Most databases provide a large number of data types to allow fine-grained control over exactly what a column can store. For example, a database might provide inbuilt support for multiple sizes of integers, or for XML data. The names of these types vary between databases. For example, in PostgreSQL the column type for booleans is `boolean`, whereas in MySQL the `tinyint(1)` type is typically used. In the blog post example above, we are using the PostgreSQL connector. This is specified in the `datasource` block of the Prisma schema. ### Default type mappings To allow you to get started with our core scalar types, Prisma ORM provides _default type mappings_ that map each scalar type to a default type in the underlying database. For example: - by default Prisma ORM's `String` type gets mapped to PostgreSQL's `text` type and MySQL's `varchar` type - by default Prisma ORM's `DateTime` type gets mapped to PostgreSQL's `timestamp(3)` type and SQL Server's `datetime2` type See Prisma ORM's [database connector pages](/orm/overview/databases) for the default type mappings for a given database. For example, [this table](/orm/overview/databases/postgresql#type-mapping-between-postgresql-and-prisma-schema) gives the default type mappings for PostgreSQL. To see the default type mappings for all databases for a specific given Prisma ORM type, see the [model field scalar types section](/orm/reference/prisma-schema-reference#model-field-scalar-types) of the Prisma schema reference. For example, [this table](/orm/reference/prisma-schema-reference#float) gives the default type mappings for the `Float` scalar type. ### Native type mappings Sometimes you may need to use a more specific database type that is not one of the default type mappings for your Prisma ORM type. For this purpose, Prisma ORM provides [native type attributes](/orm/prisma-schema/data-model/models#native-types-mapping) to refine the core scalar types. For example, in the `createdAt` field of your `Post` model above you may want to use a date-only column in your underlying PostgreSQL database, by using the `date` type instead of the default type mapping of `timestamp(3)`. To do this, add a `@db.Date` native type attribute to the `createdAt` field: ```prisma file=schema.prisma showLineNumbers model Post { id Int @id title String createdAt DateTime @db.Date } ``` Native type mappings allow you to express all the types in your database. However, you do not need to use them if the Prisma ORM defaults satisfy your needs. This leads to a shorter, more readable Prisma schema for common use cases. ## How to introspect database types When you [introspect](/orm/prisma-schema/introspection) an existing database, Prisma ORM will take the database type of each table column and represent it in your Prisma schema using the correct Prisma ORM type for the corresponding model field. If the database type is not the default database type for that Prisma ORM scalar type, Prisma ORM will also add a native type attribute. As an example, take a `User` table in a PostgreSQL database, with: - an `id` column with a data type of `serial` - a `name` column with a data type of `text` - an `isActive` column with a data type of `boolean` You can create this with the following SQL command: ```sql CREATE TABLE "public"."User" ( id serial PRIMARY KEY NOT NULL, name text NOT NULL, "isActive" boolean NOT NULL ); ``` Introspect your database with the following command run from the root directory of your project: ```terminal npx prisma db pull ``` You will get the following Prisma schema: ```prisma file=schema.prisma showLineNumbers model User { id Int @id @default(autoincrement()) name String isActive Boolean } ``` The `id`, `name` and `isActive` columns in the database are mapped respectively to the `Int`, `String` and `Boolean` Prisma ORM types. The database types are the _default_ database types for these Prisma ORM types, so Prisma ORM does not add any native type attributes. Now add a `createdAt` column to your database with a data type of `date` by running the following SQL command: ```sql ALTER TABLE "public"."User" ADD COLUMN "createdAt" date NOT NULL; ``` Introspect your database again: ```terminal npx prisma db pull ``` Your Prisma schema now includes the new `createdAt` field with a Prisma ORM type of `DateTime`. The `createdAt` field also has a `@db.Date` native type attribute, because PostgreSQL's `date` is not the default type for the `DateTime` type: ```prisma file=schema.prisma highlight=5;add showLineNumbers model User { id Int @id @default(autoincrement()) name String isActive Boolean //add-next-line createdAt DateTime @db.Date } ``` ## How to use types when you apply schema changes to your database When you apply schema changes to your database using Prisma Migrate or `db push`, Prisma ORM will use both the Prisma ORM scalar type of each field and any native attribute it has to determine the correct database type for the corresponding column in the database. As an example, create a Prisma schema with the following `Post` model: ```prisma file=schema.prisma showLineNumbers model Post { id Int @id title String createdAt DateTime updatedAt DateTime @db.Date } ``` This `Post` model has: - an `id` field with a Prisma ORM type of `Int` - a `title` field with a Prisma ORM type of `String` - a `createdAt` field with a Prisma ORM type of `DateTime` - an `updatedAt` field with a Prisma ORM type of `DateTime` and a `@db.Date` native type attribute Now apply these changes to an empty PostgreSQL database with the following command, run from the root directory of your project: ```terminal npx prisma db push ``` You will see that the database has a newly created `Post` table, with: - an `id` column with a database type of `integer` - a `title` column with a database type of `text` - a `createdAt` column with a database type of `timestamp(3)` - an `updatedAt` column with a database type of `date` Notice that the `@db.Date` native type attribute modifies the database type of the `updatedAt` column to `date`, rather than the default of `timestamp(3)`. ## More on using Prisma ORM's type system For further reference information on using Prisma ORM's type system, see the following resources: - The [database connector](/orm/overview) page for each database provider has a type mapping section with a table of default type mappings between Prisma ORM types and database types, and a table of database types with their corresponding native type attribute in Prisma ORM. For example, the type mapping section for PostgreSQL is [here](/orm/overview/databases/postgresql#type-mapping-between-postgresql-and-prisma-schema). - The [model field scalar types](/orm/reference/prisma-schema-reference#model-field-scalar-types) section of the Prisma schema reference has a subsection for each Prisma ORM scalar type. This includes a table of default mappings for that Prisma ORM type in each database, and a table for each database listing the corresponding database types and their native type attributes in Prisma ORM. For example, the entry for the `String` Prisma ORM type is [here](/orm/reference/prisma-schema-reference#string). --- # Type safety URL: https://www.prisma.io/docs/orm/prisma-client/type-safety/index The generated code for Prisma Client contains several helpful types and utilities that you can use to make your application more type-safe. This page describes patterns for leveraging them. > **Note**: If you're interested in advanced type safety topics with Prisma ORM, be sure to check out this [blog post](https://www.prisma.io/blog/satisfies-operator-ur8ys8ccq7zb) about improving your Prisma Client workflows with the new TypeScript `satisfies` keyword. ## Importing generated types You can import the `Prisma` namespace and use dot notation to access types and utilities. The following example shows how to import the `Prisma` namespace and use it to access and use the `Prisma.UserSelect` [generated type](#what-are-generated-types): ```ts import { Prisma } from '@prisma/client' // Build 'select' object const userEmail: Prisma.UserSelect = { email: true, } // Use select object const createUser = await prisma.user.create({ data: { email: 'bob@prisma.io', }, select: userEmail, }) ``` See also: [Using the `Prisma.UserCreateInput` generated type](/orm/prisma-client/queries/crud#create-a-single-record-using-generated-types) ## What are generated types? Generated types are TypeScript types that are derived from your models. You can use them to create typed objects that you pass into top-level methods like `prisma.user.create(...)` or `prisma.user.update(...)`, or options such as `select` or `include`. For example, `select` accepts an object of type `UserSelect`. Its object properties match those that are supported by `select` statements according to the model. The first tab below shows the `UserSelect` generated type and how each property on the object has a type annotation. The second tab shows the original schema from which the type was generated. ```ts type Prisma.UserSelect = { id?: boolean | undefined; email?: boolean | undefined; name?: boolean | undefined; posts?: boolean | Prisma.PostFindManyArgs | undefined; profile?: boolean | Prisma.ProfileArgs | undefined; } ``` ```prisma model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] profile Profile? } ``` In TypeScript the concept of [type annotations](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-annotations-on-variables) is when you declare a variable and add a type annotation to describe the type of the variable. See the below example. ```ts const myAge: number = 37 const myName: string = 'Rich' ``` Both of these variable declarations have been given a type annotation to specify what primitive type they are, `number` and `string` respectively. Most of the time this kind of annotation is not needed as TypeScript will infer the type of the variable based on how its initialized. In the above example `myAge` was initialized with a number so TypeScript guesses that it should be typed as a number. Going back to the `UserSelect` type, if you were to use dot notation on the created object `userEmail`, you would have access to all of the fields on the `User` model that can be interacted with using a `select` statement. ```prisma model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] profile Profile? } ``` ```ts import { Prisma } from '@prisma/client' const userEmail: Prisma.UserSelect = { email: true, } // properties available on the typed object userEmail.id userEmail.email userEmail.name userEmail.posts userEmail.profile ``` In the same mould, you can type an object with an `include` generated type then your object would have access to those properties on which you can use an `include` statement. ```ts import { Prisma } from '@prisma/client' const userPosts: Prisma.UserInclude = { posts: true, } // properties available on the typed object userPosts.posts userPosts.profile ``` > See the [model query options](/orm/reference/prisma-client-reference#model-query-options) reference for more information about the different types available. ### Generated `UncheckedInput` types The `UncheckedInput` types are a special set of generated types that allow you to perform some operations that Prisma Client considers "unsafe", like directly writing [relation scalar fields](/orm/prisma-schema/data-model/relations). You can choose either the "safe" `Input` types or the "unsafe" `UncheckedInput` type when doing operations like `create`, `update`, or `upsert`. For example, this Prisma schema has a one-to-many relation between `User` and `Post`: ```prisma model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) content String? author User @relation(fields: [authorId], references: [id]) authorId Int } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } ``` The first tab shows the `PostUncheckedCreateInput` generated type. It contains the `authorId` property, which is a relation scalar field. The second tab shows an example query that uses the `PostUncheckedCreateInput` type. This query will result in an error if a user with an `id` of `1` does not exist. ```ts type PostUncheckedCreateInput = { id?: number title: string content?: string | null authorId: number } ``` ```ts prisma.post.create({ data: { title: 'First post', content: 'Welcome to the first post in my blog...', authorId: 1, }, }) ``` The same query can be rewritten using the "safer" `PostCreateInput` type. This type does not contain the `authorId` field but instead contains the `author` relation field. ```ts type PostCreateInput = { title: string content?: string | null author: UserCreateNestedOneWithoutPostsInput } type UserCreateNestedOneWithoutPostsInput = { create?: XOR< UserCreateWithoutPostsInput, UserUncheckedCreateWithoutPostsInput > connectOrCreate?: UserCreateOrConnectWithoutPostsInput connect?: UserWhereUniqueInput } ``` ```ts prisma.post.create({ data: { title: 'First post', content: 'Welcome to the first post in my blog...', author: { connect: { id: 1, }, }, }, }) ``` This query will also result in an error if an author with an `id` of `1` does not exist. In this case, Prisma Client will give a more descriptive error message. You can also use the [`connectOrCreate`](/orm/reference/prisma-client-reference#connectorcreate) API to safely create a new user if one does not already exist with the given `id`. We recommend using the "safe" `Input` types whenever possible. ## Type utilities This feature is available from Prisma ORM version 4.9.0 upwards. To help you create highly type-safe applications, Prisma Client provides a set of type utilities that tap into input and output types. These types are fully dynamic, which means that they adapt to any given model and schema. You can use them to improve the auto-completion and developer experience of your projects. This is especially useful in [validating inputs](/orm/prisma-client/type-safety/prisma-validator) and [shared Prisma Client extensions](/orm/prisma-client/client-extensions/shared-extensions). The following type utilities are available in Prisma Client: - `Exact`: Enforces strict type safety on `Input`. `Exact` makes sure that a generic type `Input` strictly complies with the type that you specify in `Shape`. It [narrows](https://www.typescriptlang.org/docs/handbook/2/narrowing.html) `Input` down to the most precise types. - `Args`: Retrieves the input arguments for any given model and operation. This is particularly useful for extension authors who want to do the following: - Re-use existing types to extend or modify them. - Benefit from the same auto-completion experience as on existing operations. - `Result`: Takes the input arguments and provides the result for a given model and operation. You would usually use this in conjunction with `Args`. As with `Args`, `Result` helps you to re-use existing types to extend or modify them. - `Payload`: Retrieves the entire structure of the result, as scalars and relations objects for a given model and operation. For example, you can use this to determine which keys are scalars or objects at a type level. As an example, here's a quick way you can enforce that the arguments to a function matches what you will pass to a `post.create`: ```ts type PostCreateBody = Prisma.Args['data'] const addPost = async (postBody: PostCreateBody) => { const post = await prisma.post.create({ data: postBody }) return post } await addPost(myData) // ^ guaranteed to match the input of `post.create` ``` --- # Unit testing URL: https://www.prisma.io/docs/orm/prisma-client/testing/unit-testing Unit testing aims to isolate a small portion (unit) of code and test it for logically predictable behaviors. It generally involves mocking objects or server responses to simulate real world behaviors. Some benefits to unit testing include: - Quickly find and isolate bugs in code. - Provides documentation for each module of code by way of indicating what certain code blocks should be doing. - A helpful gauge that a refactor has gone well. The tests should still pass after code has been refactored. In the context of Prisma ORM, this generally means testing a function which makes database calls using Prisma Client. A single test should focus on how your function logic handles different inputs (such as a null value or an empty list). This means that you should aim to remove as many dependencies as possible, such as external services and databases, to keep the tests and their environments as lightweight as possible. > **Note**: This [blog post](https://www.prisma.io/blog/testing-series-2-xPhjjmIEsM) provides a comprehensive guide to implementing unit testing in your Express project with Prisma ORM. If you're looking to delve into this topic, be sure to give it a read! ## Prerequisites This guide assumes you have the JavaScript testing library [`Jest`](https://jestjs.io/) and [`ts-jest`](https://github.com/kulshekhar/ts-jest) already setup in your project. ## Mocking Prisma Client To ensure your unit tests are isolated from external factors you can mock Prisma Client, this means you get the benefits of being able to use your schema (**_type-safety_**), without having to make actual calls to your database when your tests are run. This guide will cover two approaches to mocking Prisma Client, a singleton instance and dependency injection. Both have their merits depending on your use cases. To help with mocking Prisma Client the [`jest-mock-extended`](https://github.com/marchaos/jest-mock-extended) package will be used. ```terminal npm install jest-mock-extended@2.0.4 --save-dev ``` At the time of writing, this guide uses `jest-mock-extended` version `^2.0.4`. ### Singleton The following steps guide you through mocking Prisma Client using a singleton pattern. 1. Create a file at your projects root called `client.ts` and add the following code. This will instantiate a Prisma Client instance. ```ts file=client.ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() export default prisma ``` 2. Next create a file named `singleton.ts` at your projects root and add the following: ```ts file=singleton.ts import { PrismaClient } from '@prisma/client' import { mockDeep, mockReset, DeepMockProxy } from 'jest-mock-extended' import prisma from './client' jest.mock('./client', () => ({ __esModule: true, default: mockDeep(), })) beforeEach(() => { mockReset(prismaMock) }) export const prismaMock = prisma as unknown as DeepMockProxy ``` The singleton file tells Jest to mock a default export (the Prisma Client instance in `./client.ts`), and uses the `mockDeep` method from `jest-mock-extended` to enable access to the objects and methods available on Prisma Client. It then resets the mocked instance before each test is run. Next, add the `setupFilesAfterEnv` property to your `jest.config.js` file with the path to your `singleton.ts` file. ```js file=jest.config.js highlight=5;add showLineNumbers module.exports = { clearMocks: true, preset: 'ts-jest', testEnvironment: 'node', //add-next-line setupFilesAfterEnv: ['/singleton.ts'], } ``` ### Dependency injection Another popular pattern that can be used is dependency injection. 1. Create a `context.ts` file and add the following: ```ts file=context.ts import { PrismaClient } from '@prisma/client' import { mockDeep, DeepMockProxy } from 'jest-mock-extended' export type Context = { prisma: PrismaClient } export type MockContext = { prisma: DeepMockProxy } export const createMockContext = (): MockContext => { return { prisma: mockDeep(), } } ``` :::tip If you find that you're seeing a circular dependency error highlighted through mocking Prisma Client, try adding `"strictNullChecks": true` to your `tsconfig.json`. ::: 2. To use the context, you would do the following in your test file: ```ts import { MockContext, Context, createMockContext } from '../context' let mockCtx: MockContext let ctx: Context beforeEach(() => { mockCtx = createMockContext() ctx = mockCtx as unknown as Context }) ``` This will create a new context before each test is run via the `createMockContext` function. This (`mockCtx`) context will be used to make a mock call to Prisma Client and run a query to test. The `ctx` context will be used to run a scenario query that is tested against. ## Example unit tests A real world use case for unit testing Prisma ORM might be a signup form. Your user fills in a form which calls a function, which in turn uses Prisma Client to make a call to your database. All of the examples that follow use the following schema model: ```prisma file=schema.prisma showLineNumbers model User { id Int @id @default(autoincrement()) email String @unique name String? acceptTermsAndConditions Boolean } ``` The following unit tests will mock the process of - Creating a new user - Updating a users name - Failing to create a user if terms are not accepted The functions that use the dependency injection pattern will have the context injected (passed in as a parameter) into them, whereas the functions that use the singleton pattern will use the singleton instance of Prisma Client. ```ts file=functions-with-context.ts import { Context } from './context' interface CreateUser { name: string email: string acceptTermsAndConditions: boolean } export async function createUser(user: CreateUser, ctx: Context) { if (user.acceptTermsAndConditions) { return await ctx.prisma.user.create({ data: user, }) } else { return new Error('User must accept terms!') } } interface UpdateUser { id: number name: string email: string } export async function updateUsername(user: UpdateUser, ctx: Context) { return await ctx.prisma.user.update({ where: { id: user.id }, data: user, }) } ``` ```ts file=functions-without-context.ts import prisma from './client' interface CreateUser { name: string email: string acceptTermsAndConditions: boolean } export async function createUser(user: CreateUser) { if (user.acceptTermsAndConditions) { return await prisma.user.create({ data: user, }) } else { return new Error('User must accept terms!') } } interface UpdateUser { id: number name: string email: string } export async function updateUsername(user: UpdateUser) { return await prisma.user.update({ where: { id: user.id }, data: user, }) } ``` The tests for each methodology are fairly similar, the difference is how the mocked Prisma Client is used. The **_dependency injection_** example passes the context through to the function that is being tested as well as using it to call the mock implementation. The **_singleton_** example uses the singleton client instance to call the mock implementation. ```ts file=__tests__/with-singleton.ts import { createUser, updateUsername } from '../functions-without-context' import { prismaMock } from '../singleton' test('should create new user ', async () => { const user = { id: 1, name: 'Rich', email: 'hello@prisma.io', acceptTermsAndConditions: true, } prismaMock.user.create.mockResolvedValue(user) await expect(createUser(user)).resolves.toEqual({ id: 1, name: 'Rich', email: 'hello@prisma.io', acceptTermsAndConditions: true, }) }) test('should update a users name ', async () => { const user = { id: 1, name: 'Rich Haines', email: 'hello@prisma.io', acceptTermsAndConditions: true, } prismaMock.user.update.mockResolvedValue(user) await expect(updateUsername(user)).resolves.toEqual({ id: 1, name: 'Rich Haines', email: 'hello@prisma.io', acceptTermsAndConditions: true, }) }) test('should fail if user does not accept terms', async () => { const user = { id: 1, name: 'Rich Haines', email: 'hello@prisma.io', acceptTermsAndConditions: false, } prismaMock.user.create.mockImplementation() await expect(createUser(user)).resolves.toEqual( new Error('User must accept terms!') ) }) ``` ```ts file=__tests__/with-dependency-injection.ts import { MockContext, Context, createMockContext } from '../context' import { createUser, updateUsername } from '../functions-with-context' let mockCtx: MockContext let ctx: Context beforeEach(() => { mockCtx = createMockContext() ctx = mockCtx as unknown as Context }) test('should create new user ', async () => { const user = { id: 1, name: 'Rich', email: 'hello@prisma.io', acceptTermsAndConditions: true, } mockCtx.prisma.user.create.mockResolvedValue(user) await expect(createUser(user, ctx)).resolves.toEqual({ id: 1, name: 'Rich', email: 'hello@prisma.io', acceptTermsAndConditions: true, }) }) test('should update a users name ', async () => { const user = { id: 1, name: 'Rich Haines', email: 'hello@prisma.io', acceptTermsAndConditions: true, } mockCtx.prisma.user.update.mockResolvedValue(user) await expect(updateUsername(user, ctx)).resolves.toEqual({ id: 1, name: 'Rich Haines', email: 'hello@prisma.io', acceptTermsAndConditions: true, }) }) test('should fail if user does not accept terms', async () => { const user = { id: 1, name: 'Rich Haines', email: 'hello@prisma.io', acceptTermsAndConditions: false, } mockCtx.prisma.user.create.mockImplementation() await expect(createUser(user, ctx)).resolves.toEqual( new Error('User must accept terms!') ) }) ``` --- # Integration testing URL: https://www.prisma.io/docs/orm/prisma-client/testing/integration-testing Integration tests focus on testing how separate parts of the program work together. In the context of applications using a database, integration tests usually require a database to be available and contain data that is convenient to the scenarios intended to be tested. One way to simulate a real world environment is to use [Docker](https://www.docker.com/get-started/) to encapsulate a database and some test data. This can be spun up and torn down with the tests and so operate as an isolated environment away from your production databases. > **Note:** This [blog post](https://www.prisma.io/blog/testing-series-2-xPhjjmIEsM) offers a comprehensive guide on setting up an integration testing environment and writing integration tests against a real database, providing valuable insights for those looking to explore this topic. ## Prerequisites This guide assumes you have [Docker](https://docs.docker.com/get-started/get-docker/) and [Docker Compose](https://docs.docker.com/compose/install/) installed on your machine as well as `Jest` setup in your project. The following ecommerce schema will be used throughout the guide. This varies from the traditional `User` and `Post` models used in other parts of the docs, mainly because it is unlikely you will be running integration tests against your blog.
Ecommerce schema ```prisma file=schema.prisma showLineNumbers // Can have 1 customer // Can have many order details model CustomerOrder { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) customer Customer @relation(fields: [customerId], references: [id]) customerId Int orderDetails OrderDetails[] } // Can have 1 order // Can have many products model OrderDetails { id Int @id @default(autoincrement()) products Product @relation(fields: [productId], references: [id]) productId Int order CustomerOrder @relation(fields: [orderId], references: [id]) orderId Int total Decimal quantity Int } // Can have many order details // Can have 1 category model Product { id Int @id @default(autoincrement()) name String description String price Decimal sku Int orderDetails OrderDetails[] category Category @relation(fields: [categoryId], references: [id]) categoryId Int } // Can have many products model Category { id Int @id @default(autoincrement()) name String products Product[] } // Can have many orders model Customer { id Int @id @default(autoincrement()) email String @unique address String? name String? orders CustomerOrder[] } ```
The guide uses a singleton pattern for Prisma Client setup. Refer to the [singleton](/orm/prisma-client/testing/unit-testing#singleton) docs for a walk through of how to set that up. ## Add Docker to your project ![Docker compose code pointing towards image of container holding a Postgres database](./Docker_Diagram_V1.png) With Docker and Docker compose both installed on your machine you can use them in your project. 1. Begin by creating a `docker-compose.yml` file at your projects root. Here you will add a Postgres image and specify the environments credentials. ```yml file=docker-compose.yml # Set the version of docker compose to use version: '3.9' # The containers that compose the project services: db: image: postgres:13 restart: always container_name: integration-tests-prisma ports: - '5433:5432' environment: POSTGRES_USER: prisma POSTGRES_PASSWORD: prisma POSTGRES_DB: tests ``` > **Note**: The compose version used here (`3.9`) is the latest at the time of writing, if you are following along be sure to use the same version for consistency. The `docker-compose.yml` file defines the following: - The Postgres image (`postgres`) and version tag (`:13`). This will be downloaded if you do not have it locally available. - The port `5433` is mapped to the internal (Postgres default) port `5432`. This will be the port number the database is exposed on externally. - The database user credentials are set and the database given a name. 2. To connect to the database in the container, create a new connection string with the credentials defined in the `docker-compose.yml` file. For example: ```env file=.env.test DATABASE_URL="postgresql://prisma:prisma@localhost:5433/tests" ``` The above `.env.test` file is used as part of a multiple `.env` file setup. Checkout the [using multiple .env files.](/orm/more/development-environment/environment-variables) section to learn more about setting up your project with multiple `.env` files 3. To create the container in a detached state so that you can continue to use the terminal tab, run the following command: ```terminal docker compose up -d ``` 4. Next you can check that the database has been created by executing a `psql` command inside the container. Make a note of the container id. ``` docker ps ``` ```code no-copy CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 1322e42d833f postgres:13 "docker-entrypoint.s…" 2 seconds ago Up 1 second 0.0.0.0:5433->5432/tcp integration-tests-prisma ``` > **Note**: The container id is unique to each container, you will see a different id displayed. 5. Using the container id from the previous step, run `psql` in the container, login with the created user and check the database is created: ``` docker exec -it 1322e42d833f psql -U prisma tests ``` ```code no-copy tests=# \l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges postgres | prisma | UTF8 | en_US.utf8 | en_US.utf8 | template0 | prisma | UTF8 | en_US.utf8 | en_US.utf8 | =c/prisma + | | | | | prisma=CTc/prisma template1 | prisma | UTF8 | en_US.utf8 | en_US.utf8 | =c/prisma + | | | | | prisma=CTc/prisma tests | prisma | UTF8 | en_US.utf8 | en_US.utf8 | (4 rows) ``` ## Integration testing Integration tests will be run against a database in a **dedicated test environment** instead of the production or development environments. ### The flow of operations The flow for running said tests goes as follows: 1. Start the container and create the database 1. Migrate the schema 1. Run the tests 1. Destroy the container Each test suite will seed the database before all the test are run. After all the tests in the suite have finished, the data from all the tables will be dropped and the connection terminated. ### The function to test The ecommerce application you are testing has a function which creates an order. This function does the following: - Accepts input about the customer making the order - Accepts input about the product being ordered - Checks if the customer has an existing account - Checks if the product is in stock - Returns an "Out of stock" message if the product doesn't exist - Creates an account if the customer doesn't exist in the database - Create the order An example of how such a function might look can be seen below: ```ts file=create-order.ts import prisma from '../client' export interface Customer { id?: number name?: string email: string address?: string } export interface OrderInput { customer: Customer productId: number quantity: number } /** * Creates an order with customer. * @param input The order parameters */ export async function createOrder(input: OrderInput) { const { productId, quantity, customer } = input const { name, email, address } = customer // Get the product const product = await prisma.product.findUnique({ where: { id: productId, }, }) // If the product is null its out of stock, return error. if (!product) return new Error('Out of stock') // If the customer is new then create the record, otherwise connect via their unique email await prisma.customerOrder.create({ data: { customer: { connectOrCreate: { create: { name, email, address, }, where: { email, }, }, }, orderDetails: { create: { total: product.price, quantity, products: { connect: { id: product.id, }, }, }, }, }, }) } ``` ### The test suite The following tests will check if the `createOrder` function works as it should do. They will test: - Creating a new order with a new customer - Creating an order with an existing customer - Show an "Out of stock" error message if a product doesn't exist Before the test suite is run the database is seeded with data. After the test suite has finished a [`deleteMany`](/orm/reference/prisma-client-reference#deletemany) is used to clear the database of its data. :::tip Using `deleteMany` may suffice in situations where you know ahead of time how your schema is structured. This is because the operations need to be executed in the correct order according to how the model relations are setup. However, this doesn't scale as well as having a more generic solution that maps over your models and performs a truncate on them. For those scenarios and examples of using raw SQL queries see [Deleting all data with raw SQL / `TRUNCATE`](/orm/prisma-client/queries/crud#deleting-all-data-with-raw-sql--truncate) ::: ```ts file=__tests__/create-order.ts import prisma from '../src/client' import { createOrder, Customer, OrderInput } from '../src/functions/index' beforeAll(async () => { // create product categories await prisma.category.createMany({ data: [{ name: 'Wand' }, { name: 'Broomstick' }], }) console.log('✨ 2 categories successfully created!') // create products await prisma.product.createMany({ data: [ { name: 'Holly, 11", phoenix feather', description: 'Harry Potters wand', price: 100, sku: 1, categoryId: 1, }, { name: 'Nimbus 2000', description: 'Harry Potters broom', price: 500, sku: 2, categoryId: 2, }, ], }) console.log('✨ 2 products successfully created!') // create the customer await prisma.customer.create({ data: { name: 'Harry Potter', email: 'harry@hogwarts.io', address: '4 Privet Drive', }, }) console.log('✨ 1 customer successfully created!') }) afterAll(async () => { const deleteOrderDetails = prisma.orderDetails.deleteMany() const deleteProduct = prisma.product.deleteMany() const deleteCategory = prisma.category.deleteMany() const deleteCustomerOrder = prisma.customerOrder.deleteMany() const deleteCustomer = prisma.customer.deleteMany() await prisma.$transaction([ deleteOrderDetails, deleteProduct, deleteCategory, deleteCustomerOrder, deleteCustomer, ]) await prisma.$disconnect() }) it('should create 1 new customer with 1 order', async () => { // The new customers details const customer: Customer = { id: 2, name: 'Hermione Granger', email: 'hermione@hogwarts.io', address: '2 Hampstead Heath', } // The new orders details const order: OrderInput = { customer, productId: 1, quantity: 1, } // Create the order and customer await createOrder(order) // Check if the new customer was created by filtering on unique email field const newCustomer = await prisma.customer.findUnique({ where: { email: customer.email, }, }) // Check if the new order was created by filtering on unique email field of the customer const newOrder = await prisma.customerOrder.findFirst({ where: { customer: { email: customer.email, }, }, }) // Expect the new customer to have been created and match the input expect(newCustomer).toEqual(customer) // Expect the new order to have been created and contain the new customer expect(newOrder).toHaveProperty('customerId', 2) }) it('should create 1 order with an existing customer', async () => { // The existing customers email const customer: Customer = { email: 'harry@hogwarts.io', } // The new orders details const order: OrderInput = { customer, productId: 1, quantity: 1, } // Create the order and connect the existing customer await createOrder(order) // Check if the new order was created by filtering on unique email field of the customer const newOrder = await prisma.customerOrder.findFirst({ where: { customer: { email: customer.email, }, }, }) // Expect the new order to have been created and contain the existing customer with an id of 1 (Harry Potter from the seed script) expect(newOrder).toHaveProperty('customerId', 1) }) it("should show 'Out of stock' message if productId doesn't exit", async () => { // The existing customers email const customer: Customer = { email: 'harry@hogwarts.io', } // The new orders details const order: OrderInput = { customer, productId: 3, quantity: 1, } // The productId supplied doesn't exit so the function should return an "Out of stock" message await expect(createOrder(order)).resolves.toEqual(new Error('Out of stock')) }) ``` ## Running the tests This setup isolates a real world scenario so that you can test your applications functionality against real data in a controlled environment. You can add some scripts to your projects `package.json` file which will setup the database and run the tests, then afterwards manually destroy the container. :::warning If the test doesn't work for you, you'll need to ensure the test database is properly set up and ready, as explained in this [blog](https://www.prisma.io/blog/testing-series-3-aBUyF8nxAn#make-the-script-wait-until-the-database-server-is-ready). ::: ```json file=package.json "scripts": { "docker:up": "docker compose up -d", "docker:down": "docker compose down", "test": "yarn docker:up && yarn prisma migrate deploy && jest -i" }, ``` The `test` script does the following: 1. Runs `docker compose up -d` to create the container with the Postgres image and database. 1. Applies the migrations found in `./prisma/migrations/` directory to the database, this creates the tables in the container's database. 1. Executes the tests. Once you are satisfied you can run `yarn docker:down` to destroy the container, its database and any test data. --- # Testing URL: https://www.prisma.io/docs/orm/prisma-client/testing/index This section describes how to approach testing an application that uses Prisma Client. --- # Deploy Prisma ORM URL: https://www.prisma.io/docs/orm/prisma-client/deployment/deploy-prisma Projects using Prisma Client can be deployed to many different cloud platforms. Given the variety of cloud platforms and different names, it's noteworthy to mention the different deployment paradigms, as they affect the way you deploy an application using Prisma Client. ## Deployment paradigms Each paradigm has different tradeoffs that affect the performance, scalability, and operational costs of your application. Moreover, the user traffic pattern of your application is also an important factor to consider. For example, any application with consistent user traffic may be better suited for a [continuously running paradigm](#traditional-servers), whereas an application with sudden spikes may be better suited to [serverless](#serverless-functions). ### Traditional servers Your application is [traditionally deployed](/orm/prisma-client/deployment/traditional) if a Node.js process is continuously running and handles multiple requests at the same time. Your application could be deployed to a Platform-as-a-Service (PaaS) like [Heroku](/orm/prisma-client/deployment/traditional/deploy-to-heroku), [Koyeb](/orm/prisma-client/deployment/traditional/deploy-to-koyeb), or [Render](/orm/prisma-client/deployment/traditional/deploy-to-render); as a Docker container to Kubernetes; or as a Node.js process on a virtual machine or bare metal server. See also: [Connection management in long-running processes](/orm/prisma-client/setup-and-configuration/databases-connections#long-running-processes) ### Serverless Functions Your application is [serverless](/orm/prisma-client/deployment/serverless) if the Node.js processes of your application (or subsets of it broken into functions) are started as requests come in, and each function only handles one request at a time. Your application would most likely be deployed to a Function-as-a-Service (FaaS) offering, such as [AWS Lambda](/orm/prisma-client/deployment/serverless/deploy-to-aws-lambda) or [Azure Functions](/orm/prisma-client/deployment/serverless/deploy-to-azure-functions) Serverless environments have the concept of warm starts, which means that for subsequent invocations of the same function, it may use an already existing container that has the allocated processes, memory, file system (`/tmp` is writable on AWS Lambda), and even DB connection still available. Typically, any piece of code [outside the handler](https://docs.aws.amazon.com/lambda/latest/dg/welcome.html) remains initialized. See also: [Connection management in serverless environments](/orm/prisma-client/setup-and-configuration/databases-connections#serverless-environments-faas) ### Edge Functions Your application is [edge deployed](/orm/prisma-client/deployment/edge) if your application is [serverless](#serverless-functions) and the functions are distributed across one or more regions close to the user. Typically, edge environments also have a different runtime than a traditional or serverless environment, leading to common APIs being unavailable. --- # Deploy to Heroku URL: https://www.prisma.io/docs/orm/prisma-client/deployment/traditional/deploy-to-heroku In this guide, you will set up and deploy a Node.js server that uses Prisma ORM with PostgreSQL to [Heroku](https://www.heroku.com). The application exposes a REST API and uses Prisma Client to handle fetching, creating, and deleting records from a database. Heroku is a cloud platform as a service (PaaS). In contrast to the popular serverless deployment model, with Heroku, your application is constantly running even if no requests are made to it. This has several benefits due to the connection limits of a PostgreSQL database. For more information, check out the [general deployment documentation](/orm/prisma-client/deployment/deploy-prisma) Typically Heroku integrates with a Git repository for automatic deployments upon commits. You can deploy to Heroku from a GitHub repository or by pushing your source to a [Git repository that Heroku creates per app](https://devcenter.heroku.com/articles/git). This guide uses the latter approach whereby you push your code to the app's repository on Heroku, which triggers a build and deploys the application. The application has the following components: - **Backend**: Node.js REST API built with Express.js with resource endpoints that use Prisma Client to handle database operations against a PostgreSQL database (e.g., hosted on Heroku). - **Frontend**: Static HTML page to interact with the API. ![architecture diagram](./images/heroku-architecture.png) The focus of this guide is showing how to deploy projects using Prisma ORM to Heroku. The starting point will be the [Prisma Heroku example](https://github.com/prisma/prisma-examples/tree/latest/deployment-platforms/heroku), which contains an Express.js server with a couple of preconfigured REST endpoints and a simple frontend. > **Note:** The various **checkpoints** throughout the guide allowing you to validate whether you performed the steps correctly. ## A note on deploying GraphQL servers to Heroku While the example uses REST, the same principles apply to a GraphQL server, with the main difference being that you typically have a single GraphQL API endpoint rather than a route for every resource as with REST. ## Prerequisites - [Heroku](https://www.heroku.com) account. - [Heroku CLI](https://devcenter.heroku.com/articles/heroku-cli) installed. - Node.js installed. - PostgreSQL CLI `psql` installed. > **Note:** Heroku doesn't provide a free plan, so billing information is required. ## Prisma ORM workflow At the core of Prisma ORM is the [Prisma schema](/orm/prisma-schema) – a declarative configuration where you define your data model and other Prisma ORM-related configuration. The Prisma schema is also a single source of truth for both Prisma Client and Prisma Migrate. In this guide, you will use [Prisma Migrate](/orm/prisma-migrate) to create the database schema. Prisma Migrate is based on the Prisma schema and works by generating `.sql` migration files that are executed against the database. Migrate comes with two primary workflows: - Creating migrations and applying during local development with `prisma migrate dev` - Applying generated migration to production with `prisma migrate deploy` For brevity, the guide does not cover how migrations are created with `prisma migrate dev`. Rather, it focuses on the production workflow and uses the Prisma schema and SQL migration that are included in the example code. You will use Heroku's [release phase](https://devcenter.heroku.com/articles/release-phase) to run the `prisma migrate deploy` command so that the migrations are applied before the application starts. To learn more about how migrations are created with Prisma Migrate, check out the [start from scratch guide](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql) ## 1. Download the example and install dependencies Open your terminal and navigate to a location of your choice. Create the directory that will hold the application code and download the example code: ```no-lines wrap mkdir prisma-heroku cd prisma-heroku curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=3 prisma-examples-latest/deployment-platforms/heroku ``` **Checkpoint:** `ls -1` should show: ```no-lines ls -1 Procfile README.md package.json prisma public src ``` Install the dependencies: ```no-lines npm install ``` > **Note:** The `Procfile` tells Heroku the command needed to start the application, i.e. `npm start`, and the command to run during the release phase, i.e., `npx prisma migrate deploy` ## 2. Create a Git repository for the application In the previous step, you downloaded the code. In this step, you will create a repository from the code so that you can push it to Heroku for deployment. To do so, run `git init` from the source code folder: ```no-lines git init > Initialized empty Git repository in /Users/alice/prisma-heroku/.git/ ``` To use the `main` branch as the default branch, run the following command: ```no-lines git branch -M main ``` With the repository initialized, add and commit the files: ```no-lines git add . git commit -m 'Initial commit' ``` **Checkpoint:** `git log -1` should show the commit: ```no-lines git log -1 commit 895534590fdd260acee6396e2e1c0438d1be7fed (HEAD -> main) ``` ## 3. Heroku CLI login Make sure you're logged in to Heroku with the CLI: ```no-lines heroku login ``` This will allow you to deploy to Heroku from the terminal. **Checkpoint:** `heroku auth:whoami` should show your username: ```no-lines heroku auth:whoami > your-email ``` ## 4. Create a Heroku app To deploy an application to Heroku, you need to create an app. You can do so with the following command: ```no-lines heroku apps:create your-app-name ``` > **Note:** Use a unique name of your choice instead of `your-app-name`. **Checkpoint:** You should see the URL and the repository for your Heroku app: ```no-lines wrap heroku apps:create your-app-name > Creating ⬢ your-app-name... done > https://your-app-name.herokuapp.com/ | https://git.heroku.com/your-app-name.git ``` Creating the Heroku app will add the git remote Heroku created to your local repository. Pushing commits to this remote will trigger a deploy. **Checkpoint:** `git remote -v` should show the Heroku git remote for your application: ```no-lines heroku https://git.heroku.com/your-app-name.git (fetch) heroku https://git.heroku.com/your-app-name.git (push) ``` If you don't see the heroku remote, use the following command to add it: ```no-lines heroku git:remote --app your-app-name ``` ## 5. Add a PostgreSQL database to your application Heroku allows your to provision a PostgreSQL database as part of an application. Create the database with the following command: ```no-lines heroku addons:create heroku-postgresql:hobby-dev ``` **Checkpoint:** To verify the database was created you should see the following: ```no-lines Creating heroku-postgresql:hobby-dev on ⬢ your-app-name... free Database has been created and is available ! This database is empty. If upgrading, you can transfer ! data from another database with pg:copy Created postgresql-parallel-73780 as DATABASE_URL ``` > **Note:** Heroku automatically sets the `DATABASE_URL` environment variable when the app is running on Heroku. Prisma ORM uses this environment variable because it's declared in the _datasource_ block of the Prisma schema (`prisma/schema.prisma`) with `env("DATABASE_URL")`. ## 6. Push to deploy Deploy the app by pushing the changes to the Heroku app repository: ```no-lines git push heroku main ``` This will trigger a build and deploy your application to Heroku. Heroku will also run the `npx prisma migrate deploy` command which executes the migrations to create the database schema before deploying the app (as defined in the `release` step of the `Procfile`). **Checkpoint:** `git push` will emit the logs from the build and release phase and display the URL of the deployed app: ```no-lines wrap remote: -----> Launching... remote: ! Release command declared: this new release will not be available until the command succeeds. remote: Released v5 remote: https://your-app-name.herokuapp.com/ deployed to Heroku remote: remote: Verifying deploy... done. remote: Running release command... remote: remote: Prisma schema loaded from prisma/schema.prisma remote: Datasource "db": PostgreSQL database "your-db-name", schema "public" at "your-db-host.compute-1.amazonaws.com:5432" remote: remote: 1 migration found in prisma/migrations remote: remote: The following migration have been applied: remote: remote: migrations/ remote: └─ 20210310152103_init/ remote: └─ migration.sql remote: remote: All migrations have been successfully applied. remote: Waiting for release.... done. ``` > **Note:** Heroku will also set the `PORT` environment variable to which your application is bound. ## 7. Test your deployed application You can use the static frontend to interact with the API you deployed via the preview URL. Open up the preview URL in your browser, the URL should like this: `https://APP_NAME.herokuapp.com`. You should see the following: ![deployed-screenshot](./images/heroku-deployed.png) The buttons allow you to make requests to the REST API and view the response: - **Check API status**: Will call the REST API status endpoint that returns `{"up":true}`. - **Seed data**: Will seed the database with a test `user` and `post`. Returns the created users. - **Load feed**: Will load all `users` in the database with their related `profiles`. For more insight into Prisma Client's API, look at the route handlers in the `src/index.js` file. You can view the application's logs with the `heroku logs --tail` command: ```no-lines wrap 2020-07-07T14:39:07.396544+00:00 app[web.1]: 2020-07-07T14:39:07.396569+00:00 app[web.1]: > prisma-heroku@1.0.0 start /app 2020-07-07T14:39:07.396569+00:00 app[web.1]: > node src/index.js 2020-07-07T14:39:07.396570+00:00 app[web.1]: 2020-07-07T14:39:07.657505+00:00 app[web.1]: 🚀 Server ready at: http://localhost:12516 2020-07-07T14:39:07.657526+00:00 app[web.1]: ⭐️ See sample requests: http://pris.ly/e/ts/rest-express#3-using-the-rest-api 2020-07-07T14:39:07.842546+00:00 heroku[web.1]: State changed from starting to up ``` ## Heroku specific notes There are some implementation details relating to Heroku that this guide addresses and are worth reiterating: - **Port binding**: web servers bind to a port so that they can accept connections. When deploying to Heroku The `PORT` environment variable is set by Heroku. Ensure you bind to `process.env.PORT` so that your application can accept requests once deployed. A common pattern is to try binding to try `process.env.PORT` and fallback to a preset port as follows: ```js const PORT = process.env.PORT || 3000 const server = app.listen(PORT, () => { console.log(`app running on port ${PORT}`) }) ``` - **Database URL**: As part of Heroku's provisioning process, a `DATABASE_URL` config var is added to your app’s configuration. This contains the URL your app uses to access the database. Ensure that your `schema.prisma` file uses `env("DATABASE_URL")` so that Prisma Client can successfully connect to the database. ## Summary Congratulations! You have successfully deployed a Node.js app with Prisma ORM to Heroku. You can find the source code for the example in [this GitHub repository](https://github.com/prisma/prisma-examples/tree/latest/deployment-platforms/heroku). For more insight into Prisma Client's API, look at the route handlers in the `src/index.js` file. --- # Deploy to Render URL: https://www.prisma.io/docs/orm/prisma-client/deployment/traditional/deploy-to-render This guide explains how to deploy a Node.js server that uses Prisma ORM and PostgreSQL to Render. The [Prisma Render deployment example](https://github.com/prisma/prisma-examples/tree/latest/deployment-platforms/render) contains an Express.js application with REST endpoints and a simple frontend. This app uses Prisma Client to fetch, create, and delete records from its database. ## About Render [Render](https://render.com) is a cloud application platform that lets developers easily deploy and scale full-stack applications. For this example, it's helpful to know: - Render lets you deploy long-running, "serverful" full-stack applications. You can configure Render services to [autoscale](https://docs.render.com/scaling) based on CPU and/or memory usage. This is one of several [deployment paradigms](/orm/prisma-client/deployment/deploy-prisma) you can choose from. - Render natively supports [common runtimes](https://docs.render.com/language-support), including Node.js and Bun. In this guide, we'll use the Node.js runtime. - Render [integrates with Git repos](https://docs.render.com/github) for automatic deployments upon commits. You can deploy to Render from GitHub, GitLab, or Bitbucket. In this guide, we'll deploy from a Git repository. ## Prerequisites - Sign up for a [Render](https://render.com) account ## Get the example code Download the [example code](https://github.com/prisma/prisma-examples/tree/latest/deployment-platforms/render) to your local machine. ```terminal curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=2 prisma-examples-latest/deployment-platforms/render cd render ``` ## Understand the example Before we deploy the app, let's take a look at the example code. ### Web application The logic for the Express app is in two files: - `src/index.js`: The API. The endpoints use Prisma Client to fetch, create, and delete data from the database. - `public/index.html`: The web frontend. The frontend calls a few of the API endpoints. ### Prisma schema and migrations The Prisma components of this app are in two files: - `prisma/schema.prisma`: The data model of this app. This example defines two models, `User` and `Post`. The format of this file follows the [Prisma schema](/orm/prisma-schema/overview). - `prisma/migrations//migration.sql`: The SQL commands that construct this schema in a PostgreSQL database. You can auto-generate migration files like this one by running [`prisma migrate dev`](/orm/prisma-migrate/understanding-prisma-migrate/mental-model#what-is-prisma-migrate). ### Render Blueprint The `render.yaml` file is a [Render blueprint](https://docs.render.com/infrastructure-as-code). Blueprints are Render's Infrastructure as Code format. You can use a Blueprint to programmatically create and modify services on Render. A `render.yaml` defines the services that will be spun up on Render by a Blueprint. In this `render.yaml`, we see: - **A web service that uses a Node runtime**: This is the Express app. - **A PostgreSQL database**: This is the database that the Express app uses. The format of this file follows the [Blueprint specification](https://docs.render.com/blueprint-spec). ### How Render deploys work with Prisma Migrate In general, you want all your database migrations to run before your web app is started. Otherwise, the app may hit errors when it queries a database that doesn't have the expected tables and rows. You can use the Pre-Deploy Command setting in a Render deploy to run any commands, such as database migrations, before the app is started. For more details about the Pre-Deploy Command, see [Render's deploy guide](https://docs.render.com/deploys#deploy-steps). In our example code, the `render.yaml` shows the web service's build command, pre-deploy command, and start command. Notably, `npx prisma migrate deploy` (the pre-deploy command) will run before `npm run start` (the start command). | **Command** | **Value** | | :----------------- | :--------------------------- | | Build Command | `npm install --production=false` | | Pre-Deploy Command | `npx prisma migrate deploy` | | Start Command | `npm run start` | ## Deploy the example ### 1. Initialize your Git repository 1. Download [the example code](https://github.com/prisma/prisma-examples/tree/latest/deployment-platforms/render) to your local machine. 2. Create a new Git repository on GitHub, GitLab, or BitBucket. 3. Upload the example code to your new repository. ### 2. Deploy manually 1. In the Render Dashboard, click **New** > **PostgreSQL**. Provide a database name, and select a plan. (The Free plan works for this demo.) 2. After your database is ready, look up its [internal URL](https://docs.render.com/postgresql-creating-connecting#internal-connections). 3. In the Render Dashboard, click **New** > **Web Service** and connect the Git repository that contains the example code. 4. Provide the following values during service creation: | **Setting** | **Value** | | :-------------------- | :--------------------------- | | Language | `Node` | | Build Command | `npm install --production=false` | | Pre-Deploy Command (Note: this may be in the "Advanced" tab) | `npx prisma migrate deploy` | | Start Command | `npm run start` | | Environment Variables | Set `DATABASE_URL` to the internal URL of the database | That’s it. Your web service will be live at its `onrender.com` URL as soon as the build finishes. ### 3. (optional) Deploy with Infrastructure as Code You can also deploy the example using the Render Blueprint. Follow Render's [Blueprint setup guide] and use the `render.yaml` in the example. ## Bonus: Seed the database Prisma ORM includes a framework for [seeding the database](/orm/prisma-migrate/workflows/seeding) with starter data. In our example, `prisma/seed.js` defines some test users and posts. To add these users to the database, we can either: 1. Add the seed script to our Pre-Deploy Command, or 2. Manually run the command on our server via an SSH shell ### Method 1: Pre-Deploy Command If you manually deployed your Render services: 1. In the Render dashboard, navigate to your web service. 2. Select **Settings**. 3. Set the Pre-Deploy Command to: `npx prisma migrate deploy; npx prisma db seed` If you deployed your Render services using the Blueprint: 1. In your `render.yaml` file, change the `preDeployCommand` to: `npx prisma migrate deploy; npx prisma db seed` 2. Commit the change to your Git repo. ### Method 2: SSH Render allows you to SSH into your web service. 1. Follow [Render's SSH guide](https://docs.render.com/ssh) to connect to your server. 2. In the shell, run: `npx prisma db seed` --- # Deploy to Koyeb URL: https://www.prisma.io/docs/orm/prisma-client/deployment/traditional/deploy-to-koyeb In this guide, you will set up and deploy a Node.js server that uses Prisma ORM with PostgreSQL to [Koyeb](https://www.koyeb.com/). The application exposes a REST API and uses Prisma Client to handle fetching, creating, and deleting records from a database. Koyeb is a developer-friendly serverless platform to deploy apps globally. The platform lets you seamlessly run Docker containers, web apps, and APIs with git-based deployment, TLS encryption, native autoscaling, a global edge network, and built-in service mesh & discovery. When using the [Koyeb git-driven deployment](https://www.koyeb.com/docs/build-and-deploy/build-from-git) method, each time you push code changes to a GitHub repository a new build and deployment of the application are automatically triggered on the Koyeb Serverless Platform. This guide uses the latter approach whereby you push your code to the app's repository on GitHub. The application has the following components: - **Backend**: Node.js REST API built with Express.js with resource endpoints that use Prisma Client to handle database operations against a PostgreSQL database (e.g., hosted on Heroku). - **Frontend**: Static HTML page to interact with the API. ![architecture diagram](./images/koyeb-architecture.png) The focus of this guide is showing how to deploy projects using Prisma ORM to Koyeb. The starting point will be the [Prisma Koyeb example](https://github.com/koyeb/example-prisma), which contains an Express.js server with a couple of preconfigured REST endpoints and a simple frontend. > **Note:** The various **checkpoints** throughout the guide allow you to validate whether you performed the steps correctly. ## Prerequisites - Hosted PostgreSQL database and a URL from which it can be accessed, e.g. `postgresql://username:password@your_postgres_db.cloud.com/db_identifier` (you can use Supabase, which offers a [free plan](https://dev.to/prisma/set-up-a-free-postgresql-database-on-supabase-to-use-with-prisma-3pk6)). - [GitHub](https://github.com) account with an empty public repository we will use to push the code. - [Koyeb](https://www.koyeb.com) account. - Node.js installed. ## Prisma ORM workflow At the core of Prisma ORM is the [Prisma schema](/orm/prisma-schema) – a declarative configuration where you define your data model and other Prisma ORM-related configuration. The Prisma schema is also a single source of truth for both Prisma Client and Prisma Migrate. In this guide, you will create the database schema with [Prisma Migrate](/orm/prisma-migrate) to create the database schema. Prisma Migrate is based on the Prisma schema and works by generating `.sql` migration files that are executed against the database. Migrate comes with two primary workflows: - Creating migrations and applying them during local development with `prisma migrate dev` - Applying generated migration to production with `prisma migrate deploy` For brevity, the guide does not cover how migrations are created with `prisma migrate dev`. Rather, it focuses on the production workflow and uses the Prisma schema and SQL migration that are included in the example code. You will use Koyeb's [build step](https://www.koyeb.com/docs/build-and-deploy/build-from-git#the-buildpack-build-process) to run the `prisma migrate deploy` command so that the migrations are applied before the application starts. To learn more about how migrations are created with Prisma Migrate, check out the [start from scratch guide](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-postgresql) ## 1. Download the example and install dependencies Open your terminal and navigate to a location of your choice. Create the directory that will hold the application code and download the example code: ```no-lines wrap mkdir prisma-on-koyeb cd prisma-on-koyeb curl https://github.com/koyeb/example-prisma/tarball/main/latest | tar xz --strip=1 ``` **Checkpoint:** Executing the `tree` command should show the following directories and files: ```no-lines . ├── README.md ├── package.json ├── prisma │   ├── migrations │   │   ├── 20210310152103_init │   │   │   └── migration.sql │   │   └── migration_lock.toml │   └── schema.prisma ├── public │   └── index.html └── src └── index.js 5 directories, 8 files ``` Install the dependencies: ```no-lines npm install ``` ## 2. Initialize a Git repository and push the application code to GitHub In the previous step, you downloaded the code. In this step, you will create a repository from the code so that you can push it to a GitHub repository for deployment. To do so, run `git init` from the source code folder: ```no-lines git init > Initialized empty Git repository in /Users/edouardb/prisma-on-koyeb/.git/ ``` With the repository initialized, add and commit the files: ```no-lines git add . git commit -m 'Initial commit' ``` **Checkpoint:** `git log -1` should show the commit: ```no-lines git log -1 commit 895534590fdd260acee6396e2e1c0438d1be7fed (HEAD -> main) ``` Then, push the code to your GitHub repository by adding the remote ```no-lines git remote add origin git@github.com:/.git git push -u origin main ``` ## 3. Deploy the application on Koyeb On the [Koyeb Control Panel](https://app.koyeb.com), click the **Create App** button. You land on the Koyeb App creation page where you are asked for information about the application to deploy such as the deployment method to use, the repository URL, the branch to deploy, the build and run commands to execute. Pick GitHub as the deployment method and select the GitHub repository containing your application and set the branch to deploy to `main`. > **Note:** If this is your first time using Koyeb, you will be prompted to install the Koyeb app in your GitHub account. In the **Environment variables** section, create a new environment variable `DATABASE_URL` that is type Secret. In the value field, click **Create Secret**, name your secret `prisma-pg-url` and set the PostgreSQL database connection string as the secret value which should look as follows: `postgresql://__USER__:__PASSWORD__@__HOST__/__DATABASE__`. [Koyeb Secrets](https://www.koyeb.com/docs/reference/secrets) allow you to securely store and retrieve sensitive information like API tokens, database connection strings. They enable you to secure your code by removing hardcoded credentials and let you pass environment variables securely to your applications. Last, give your application a name and click the **Create App** button. **Checkpoint:** Open the deployed app by clicking on the screenshot of the deployed app. Once the page loads, click on the **Check API status** button, which should return: `{"up":true}` ![deployed-screenshot](./images/koyeb-app-creation.png) Congratulations! You have successfully deployed the app to Koyeb. Koyeb will build and deploy the application. Additional commits to your GitHub repository will trigger a new build and deployment on Koyeb. **Checkpoint:** Once the build and deployment are completed, you can access your application by clicking the App URL ending with koyeb.app in the Koyeb control panel. Once on the app page loads, Once the page loads, click on the **Check API status** button, which should return: `{"up":true}` ## 4. Test your deployed application You can use the static frontend to interact with the API you deployed via the preview URL. Open up the preview URL in your browser, the URL should like this: `https://APP_NAME-ORG_NAME.koyeb.app`. You should see the following: ![deployed-screenshot](./images/koyeb-deployed.png) The buttons allow you to make requests to the REST API and view the response: - **Check API status**: Will call the REST API status endpoint that returns `{"up":true}`. - **Seed data**: Will seed the database with a test `user` and `post`. Returns the created users. - **Load feed**: Will load all `users` in the database with their related `profiles`. For more insight into Prisma Client's API, look at the route handlers in the `src/index.js` file. You can view the application's logs clicking the `Runtime logs` tab on your app service from the Koyeb control panel: ```no-lines wrap node-72d14691 stdout > prisma-koyeb@1.0.0 start node-72d14691 stdout > node src/index.js node-72d14691 stdout 🚀 Server ready at: http://localhost:8080 node-72d14691 stdout ⭐️ See sample requests: http://pris.ly/e/ts/rest-express#3-using-the-rest-api ``` ## Koyeb specific notes ### Build By default, for applications using the Node.js runtime, if the `package.json` contains a `build` script, Koyeb automatically executes it after the dependencies installation. In the example, the `build` script is used to run `prisma generate && prisma migrate deploy && next build`. ### Deployment By default, for applications using the Node.js runtime, if the `package.json` contains a `start` script, Koyeb automatically executes it to launch the application. In the example, the `start` script is used to run `node src/index.js`. ### Database migrations and deployments In the example you deployed, migrations are applied using the `prisma migrate deploy` command during the Koyeb build (as defined in the `build` script in `package.json`). ### Additional notes In this guide, we kept pre-set values for the region, instance size, and horizontal scaling. You can customize them according to your needs. > **Note:** The Ports section is used to let Koyeb know which port your application is listening to and properly route incoming HTTP requests. A default `PORT` environment variable is set to `8080` and incoming HTTP requests are routed to the `/` path when creating a new application. > If your application is listening on another port, you can define another port to route incoming HTTP requests. ## Summary Congratulations! You have successfully deployed a Node.js app with Prisma ORM to Koyeb. You can find the source code for the example in [this GitHub repository](https://github.com/koyeb/example-prisma). For more insight into Prisma Client's API, look at the route handlers in the `src/index.js` file. --- # Deploy to Fly.io URL: https://www.prisma.io/docs/orm/prisma-client/deployment/traditional/deploy-to-flyio This guide explains how to deploy a Node.js server that uses Prisma ORM and PostgreSQL to Fly.io. The [Prisma Render deployment example](https://github.com/prisma/prisma-examples/tree/latest/deployment-platforms/render) contains an Express.js application with REST endpoints and a simple frontend. This app uses Prisma Client to fetch, create, and delete records from its database. This guide will show you how to deploy the same application, without modification, on Fly.io. ## About Fly.io [fly.io](https://fly.io/) is a cloud application platform that lets developers easily deploy and scale full-stack applications that start on request near on machines near to users. For this example, it's helpful to know: - Fly.io lets you deploy long-running, "serverful" full-stack applications in [35 regions around the world](https://fly.io/docs/reference/regions/). By default, applications are configured to to [auto-stop](https://fly.io/docs/launch/autostop-autostart/) when not in use, and auto-start as needed as requests come in. - Fly.io natively supports a wide variety of [languages and frameworks](https://fly.io/docs/languages-and-frameworks/), including Node.js and Bun. In this guide, we'll use the Node.js runtime. - Fly.io can [launch apps directly from GitHub](https://fly.io/speedrun). When run from the CLI, `fly launch` will automatically configure applications hosted on GitHub to deploy on push. ## Prerequisites - Sign up for a [Fly.io](https://fly.io/docs/getting-started/launch/) account ## Get the example code Download the [example code](https://github.com/prisma/prisma-examples/tree/latest/deployment-platforms/render) to your local machine. ```terminal curl https://codeload.github.com/prisma/prisma-examples/tar.gz/latest | tar -xz --strip=2 prisma-examples-latest/deployment-platforms/render cd render ``` ## Understand the example Before we deploy the app, let's take a look at the example code. ### Web application The logic for the Express app is in two files: - `src/index.js`: The API. The endpoints use Prisma Client to fetch, create, and delete data from the database. - `public/index.html`: The web frontend. The frontend calls a few of the API endpoints. ### Prisma schema and migrations The Prisma components of this app are in three files: - `prisma/schema.prisma`: The data model of this app. This example defines two models, `User` and `Post`. The format of this file follows the [Prisma schema](/orm/prisma-schema/overview). - `prisma/migrations//migration.sql`: The SQL commands that construct this schema in a PostgreSQL database. You can auto-generate migration files like this one by running [`prisma migrate dev`](/orm/prisma-migrate/understanding-prisma-migrate/mental-model#what-is-prisma-migrate). - `prisma/seed.js`: defines some test users and postsPrisma, used to [seed the database](/orm/prisma-migrate/workflows/seeding) with starter data. ## Deploy the example ### 1. Run `fly launch` and accept the defaults That’s it. Your web service will be live at its `fly.dev` URL as soon as the deploy completes. Optionally [scale](https://fly.io/docs/launch/scale-count/) the size, number, and placement of machines as desired. [`fly console`](https://fly.io/docs/flyctl/console/) can be used to ssh into a new or existing machine. More information can be found on in the [fly.io documentation](https://fly.io/docs/js/prisma/). --- # Traditional servers URL: https://www.prisma.io/docs/orm/prisma-client/deployment/traditional/index If your application is deployed via a Platform-as-a-Service (PaaS) provider, whether containerized or not, it is a traditionally-deployed app. Common deployment examples include [Heroku](/orm/prisma-client/deployment/traditional/deploy-to-heroku) and [Koyeb](/orm/prisma-client/deployment/traditional/deploy-to-koyeb). ## Traditional (PaaS) guides --- # Deploy to Azure Functions URL: https://www.prisma.io/docs/orm/prisma-client/deployment/serverless/deploy-to-azure-functions This guide explains how to avoid common issues when deploying a Node.js-based function app to Azure using [Azure Functions](https://azure.microsoft.com/en-us/products/functions/). Azure Functions is a serverless deployment platform. You do not need to maintain infrastructure to deploy your code. With Azure Functions, the fundamental building block is the [function app](https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference?tabs=blob&pivots=programming-language-typescript). A function app provides an execution context in Azure in which your functions run. It is comprised of one or more individual functions that Azure manages, deploys, and scales together. You can organize and collectively manage multiple functions as a single logical unit. ## Prerequisites - An existing function app project with Prisma ORM ## Things to know While Prisma ORM works well with Azure functions, there are a few things to take note of before deploying your application. ### Define multiple binary targets When deploying a function app, the operating system that Azure functions runs a remote build is different from the one used to host your functions. Therefore, we recommend specifying the following [`binaryTargets` options](/orm/reference/prisma-schema-reference#binarytargets-options) in your Prisma schema: ```prisma file=schema.prisma highlight=3;normal showLineNumbers generator client { provider = "prisma-client-js" //highlight-next-line binaryTargets = ["native", "debian-openssl-1.1.x"] } ``` ### Connection pooling Generally, when you use a FaaS (Function as a Service) environment to interact with a database, every function invocation can result in a new connection to the database. This is not a problem with a constantly running Node.js server. Therefore, it is beneficial to pool DB connections to get better performance. To solve this issue, you can use the [Prisma Accelerate](/accelerate). For other solutions, see the [connection management guide for serverless environments](/orm/prisma-client/setup-and-configuration/databases-connections#serverless-environments-faas). ## Summary For more insight into Prisma Client's API, explore the function handlers and check out the [Prisma Client API Reference](/orm/reference/prisma-client-reference) --- # Deploy to Vercel URL: https://www.prisma.io/docs/orm/prisma-client/deployment/serverless/deploy-to-vercel This guide takes you through the steps to set up and deploy a serverless application that uses Prisma to [Vercel](https://vercel.com/). Vercel is a cloud platform that hosts static sites, serverless, and edge functions. You can integrate a Vercel project with a GitHub repository to allow you to deploy automatically when you make new commits. We created an [example application](https://github.com/prisma/deployment-example-vercel) using Next.js you can use as a reference when deploying an application using Prisma to Vercel. While our examples use Next.js, you can deploy other applications to Vercel. See [Using Express with Vercel](https://vercel.com/guides/using-express-with-vercel) and [Nuxt on Vercel](https://vercel.com/docs/frameworks/nuxt) as examples of other options. ## Build configuration ### Updating Prisma Client during Vercel builds Vercel will automatically cache dependencies on deployment. For most applications, this will not cause any issues. However, for Prisma ORM, it may result in an outdated version of Prisma Client on a change in your Prisma schema. To avoid this issue, add `prisma generate` to the `postinstall` script of your application: ```json file=package.json showLineNumbers { ... "scripts" { //add-next-line "postinstall": "prisma generate" } ... } ``` This will re-generate Prisma Client at build time so that your deployment always has an up-to-date client. :::info If you see `prisma: command not found` errors during your deployment to Vercel, you are missing `prisma` in your dependencies. By default, `prisma` is a dev dependency and may need to be moved to be a standard dependency. ::: Another option to avoid an outdated Prisma Client is to use [a custom output path](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path) and check your client into version control. This way each deployment is guaranteed to include the correct Prisma Client. ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" //add-next-line output = "./generated/client" } ``` ### Deploying Prisma in Monorepos on Vercel If you are using Prisma inside a monorepo (e.g., with TurboRepo) and deploying to Vercel, you may encounter issues where required files—such as `libquery_engine-rhel-openssl-3.0.x.so.node` are missing from the deployed bundle. This is because Vercel aggressively optimizes serverless deployments, sometimes stripping out necessary Prisma files. To resolve this, use the [@prisma/nextjs-monorepo-workaround-plugin](https://www.npmjs.com/package/@prisma/nextjs-monorepo-workaround-plugin) plugin, which ensures that Prisma engine files are correctly included in the final bundle. For more details on how Prisma interacts with different bundlers like Webpack and Parcel, see our [Module bundlers](/orm/prisma-client/deployment/module-bundlers#overview) page. ### CI/CD workflows In a more sophisticated CI/CD environment, you may additonally want to update the database schema with any migrations you have performed during local development. You can do this using the [`prisma migrate deploy`](/orm/reference/prisma-cli-reference#migrate-deploy) command. In that case, you could create a custom build command in your `package.json` (e.g. called `vercel-build`) that looks as follows: ```json file=package.json { ... "scripts" { //add-next-line "vercel-build": "prisma generate && prisma migrate deploy && next build", } ... } ``` You can invoke this script inside your CI/CD pipeline using the following command: ```terminal npm run vercel-build ``` ## Add a separate database for preview deployments By default, your application will have a single _production_ environment associated with the `main` git branch of your repository. If you open a pull request to change your application, Vercel creates a new _preview_ environment. Vercel uses the `DATABASE_URL` environment variable you define when you import the project for both the production and preview environments. This causes problems if you create a pull request with a database schema migration because the pull request will change the schema of the production database. To prevent this, use a _second_ hosted database to handle preview deployments. Once you have that connection string, you can add a `DATABASE_URL` for your preview environment using the Vercel dashboard: 1. Click the **Settings** tab of your Vercel project. 2. Click **Environment variables**. 3. Add an environment variable with a key of `DATABASE_URL` and select only the **Preview** environment option: ![Add an environment variable for the preview environment](./images/300-60-deploy-to-vercel-preview-environment-variable.png) 4. Set the value to the connection string of your second database: ```code postgresql://dbUsername:dbPassword@myhost:5432/mydb ``` 5. Click **Save**. ## Connection pooling When you use a Function-as-a-Service provider, like Vercel Serverless functions, every invocation may result in a new connection to your database. This can cause your database to quickly run out of open connections and cause your application to stall. For this reason, pooling connections to your database is essential. You can use [Accelerate](/accelerate) for connection pooling or [Prisma Postgres](/postgres), which has built-in connection pooling, to reduce your Prisma Client bundle size, and to avoid cold starts. For more information on connection management for serverless environments, refer to our [connection management guide](/orm/prisma-client/setup-and-configuration/databases-connections#serverless-environments-faas). --- # Deploy to AWS Lambda URL: https://www.prisma.io/docs/orm/prisma-client/deployment/serverless/deploy-to-aws-lambda This guide explains how to avoid common issues when deploying a project using Prisma ORM to [AWS Lambda](https://aws.amazon.com/lambda/). While a deployment framework is not required to deploy to AWS Lambda, this guide covers deploying with: - [AWS Serverless Application Model (SAM)](https://aws.amazon.com/serverless/sam/) is an open-source framework from AWS that can be used in the creation of serverless applications. AWS SAM includes the [AWS SAM CLI](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-reference.html#serverless-sam-cli), which you can use to build, test, and deploy your application. - [Serverless Framework](https://www.serverless.com/framework) provides a CLI that helps with workflow automation and AWS resource provisioning. While Prisma ORM works well with the Serverless Framework "out of the box", there are a few improvements that can be made within your project to ensure a smooth deployment and performance. There is also additional configuration that is needed if you are using the [`serverless-webpack`](https://www.npmjs.com/package/serverless-webpack) or [`serverless-bundle`](https://www.npmjs.com/package/serverless-bundle) libraries. - [SST](https://sst.dev/) provides tools that make it easy for developers to define, test, debug, and deploy their applications. Prisma ORM works well with SST but must be configured so that your schema is correctly packaged by SST. ## General considerations when deploying to AWS Lambda This section covers changes you will need to make to your application, regardless of framework. After following these steps, follow the steps for your framework. - [Deploying with AWS SAM](#deploying-with-aws-sam) - [Deploying with the Serverless Framework](#deploying-with-the-serverless-framework) - [Deploying with SST](#deploying-with-sst) ### Define binary targets in Prisma Schema Depending on the version of Node.js, your Prisma schema should contain either `rhel-openssl-1.0.x` or `rhel-openssl-3.0.x` in the `generator` block: ```prisma binaryTargets = ["native", "rhel-openssl-1.0.x"] ``` ```prisma binaryTargets = ["native", "rhel-openssl-3.0.x"] ``` This is necessary because the runtimes used in development and deployment differ. Add the [`binaryTarget`](/orm/reference/prisma-schema-reference#binarytargets-options) to make the compatible Prisma ORM engine file available. #### Lambda functions with arm64 architectures Lambda functions that use [arm64 architectures (AWS Graviton2 processor)](https://docs.aws.amazon.com/lambda/latest/dg/foundation-arch.html#foundation-arch-adv) must use an `arm64` precompiled engine file. In the `generator` block of your `schema.prisma` file, add the following: ```prisma file=schema.prisma showLineNumbers binaryTargets = ["native", "linux-arm64-openssl-1.0.x"] ``` ### Prisma CLI binary targets While we do not recommend running migrations within AWS Lambda, some applications will require it. In these cases, you can use the [PRISMA_CLI_BINARY_TARGETS](/orm/reference/environment-variables-reference#prisma_cli_binary_targets) environment variable to make sure that Prisma CLI commands, including `prisma migrate`, have access to the correct schema engine. In the case of AWS lambda, you will have to add the following environment variable: ```env file=.env showLineNumbers PRISMA_CLI_BINARY_TARGETS=native,rhel-openssl-1.0.x ``` :::info `prisma migrate` is a command in the `prisma` package. Normally, this package is installed as a dev dependency. Depending on your setup, you may need to install this package as a dependency instead so that it is included in the bundle or archive that is uploaded to Lambda and executed. ::: ### Connection pooling In a Function as a Service (FaaS) environment, each function invocation typically creates a new database connection. Unlike a continuously running Node.js server, these connections aren't maintained between executions. For better performance in serverless environments, implement connection pooling to reuse existing database connections rather than creating new ones for each function call. You can use [Accelerate](/accelerate) for connection pooling or [Prisma Postgres](/postgres), which has built-in connection pooling, to solve this issue. For other solutions, see the [connection management guide for serverless environments](/orm/prisma-client/setup-and-configuration/databases-connections#serverless-environments-faas). ## Deploying with AWS SAM ### Loading environment variables AWS SAM does not directly support loading values from a `.env` file. You will have to use one of AWS's services to store and retrieve these parameters. [This guide](https://medium.com/bip-xtech/a-practical-guide-to-surviving-aws-sam-d8ab141b3d25) provides a great overview of your options and how to store and retrieve values in Parameters, SSM, Secrets Manager, and more. ### Loading required files AWS SAM uses [esbuild](https://esbuild.github.io/) to bundle your TypeScript code. However, the full esbuild API is not exposed and esbuild plugins are not supported. This leads to problems when using Prisma ORM in your application as certain files (like `schema.prisma`) must be available at runtime. To get around this, you need to directly reference the needed files in your code to bundle them correctly. In your application, you could add the following lines to your application where Prisma ORM is instantiated. ```ts file=app.ts showLineNumbers import schema from './prisma/schema.prisma' import x from './node_modules/.prisma/client/libquery_engine-rhel-openssl-1.0.x.so.node' if (process.env.NODE_ENV !== 'production') { console.debug(schema, x) } ``` ## Deploying with the Serverless Framework ### Loading environment variables via a `.env` file Your functions will need the `DATABASE_URL` environment variable to access the database. The `serverless-dotenv-plugin` will allow you to use your `.env` file in your deployments. First, make sure that the plugin is installed: ```terminal npm install -D serverless-dotenv-plugin ``` Then, add `serverless-dotenv-plugin` to your list of plugins in `serverless.yml`: ```code file=serverless.yml no-copy showLineNumbers plugins: - serverless-dotenv-plugin ``` The environment variables in your `.env` file will now be automatically loaded on package or deployment. ```terminal serverless package ``` ```terminal no-copy Running "serverless" from node_modules DOTENV: Loading environment variables from .env: - DATABASE_URL Packaging deployment-example-sls for stage dev (us-east-1) . . . ``` ### Deploy only the required files To reduce your deployment footprint, you can update your deployment process to only upload the files your application needs. The Serverless configuration file, `serverless.yml`, below shows a `package` pattern that includes only the Prisma ORM engine file relevant to the Lambda runtime and excludes the others. This means that when Serverless Framework packages your app for upload, it includes only one engine file. This ensures the packaged archive is as small as possible. ```code file=serverless.yml no-copy showLineNumbers package: patterns: - '!node_modules/.prisma/client/libquery_engine-*' - 'node_modules/.prisma/client/libquery_engine-rhel-*' - '!node_modules/prisma/libquery_engine-*' - '!node_modules/@prisma/engines/**' - '!node_modules/.cache/prisma/**' # only required for Windows ``` If you are deploying to [Lambda functions with ARM64 architecture](#lambda-functions-with-arm64-architectures) you should update the Serverless configuration file to package the `arm64` engine file, as follows: ```code file=serverless.yml highlight=4;normal showLineNumbers package: patterns: - '!node_modules/.prisma/client/libquery_engine-*' //highlight-next-line - 'node_modules/.prisma/client/libquery_engine-linux-arm64-*' - '!node_modules/prisma/libquery_engine-*' - '!node_modules/@prisma/engines/**' ``` If you use `serverless-webpack`, see [Deployment with serverless webpack](#deployment-with-serverless-webpack) below. ### Deployment with `serverless-webpack` If you use `serverless-webpack`, you will need additional configuration so that your `schema.prisma` is properly bundled. You will need to: 1. Copy your `schema.prisma` with [`copy-webpack-plugin`](https://www.npmjs.com/package/copy-webpack-plugin). 2. Run `prisma generate` via `custom > webpack > packagerOptions > scripts` in your `serverless.yml`. 3. Only package the correct Prisma ORM engine file to save more than 40mb of capacity. #### 1. Install webpack specific dependencies First, ensure the following webpack dependencies are installed: ```terminal npm install --save-dev webpack webpack-node-externals copy-webpack-plugin serverless-webpack ``` #### 2. Update `webpack.config.js` In your `webpack.config.js`, make sure that you set `externals` to `nodeExternals()` like the following: ```javascript file=webpack.config.js highlight=1,5;normal; showLineNumbers const nodeExternals = require('webpack-node-externals') module.exports = { // ... other configuration //highlight-next-line externals: [nodeExternals()], // ... other configuration } ``` Update the `plugins` property in your `webpack.config.js` file to include the `copy-webpack-plugin`: ```javascript file=webpack.config.js highlight=2,7-13;normal; showLineNumbers const nodeExternals = require('webpack-node-externals') //highlight-next-line const CopyPlugin = require('copy-webpack-plugin') module.exports = { // ... other configuration externals: [nodeExternals()], //highlight-start plugins: [ new CopyPlugin({ patterns: [ { from: './node_modules/.prisma/client/schema.prisma', to: './' }, // you may need to change `to` here. ], }), ], //highlight-end // ... other configuration } ``` This plugin will allow you to copy your `schema.prisma` file into your bundled code. Prisma ORM requires that your `schema.prisma` be present in order make sure that queries are encoded and decoded according to your schema. In most cases, bundlers will not include this file by default and will cause your application to fail to run. :::info Depending on how your application is bundled, you may need to copy the schema to a location other than `./`. Use the `serverless package` command to package your code locally so you can review where your schema should be put. ::: Refer to the [Serverless Webpack documentation](https://www.serverless.com/plugins/serverless-webpack) for additional configuration. #### 3. Update `serverless.yml` In your `serverless.yml` file, make sure that the `custom > webpack` block has `prisma generate` under `packagerOptions > scripts` as follows: ```yaml file=serverless.yml showLineNumbers custom: webpack: packagerOptions: scripts: - prisma generate ``` This will ensure that, after webpack bundles your code, the Prisma Client is generated according to your schema. Without this step, your app will fail to run. Lastly, you will want to exclude [Prisma ORM query engines](/orm/more/under-the-hood/engines) that do not match the AWS Lambda runtime. Update your `serverless.yml` by adding the following script that makes sure only the required query engine, `rhel-openssl-1.0.x`, is included in the final packaged archive. ```yaml file=serverless.yml highlight=6;add showLineNumbers custom: webpack: packagerOptions: scripts: - prisma generate //add-next-line -- find . -name "libquery_engine-*" -not -name "libquery_engine-rhel-openssl-*" | xargs rm ``` If you are deploying to [Lambda functions with ARM64 architecture](#lambda-functions-with-arm64-architectures) you should update the `find` command to the following: ```yaml file=serverless.yml highlight=6;add showLineNumbers custom: webpack: packagerOptions: scripts: - prisma generate //add-next-line -- find . -name "libquery_engine-*" -not -name "libquery_engine-arm64-openssl-*" | xargs rm ``` #### 4. Wrapping up You can now re-package and re-deploy your application. To do so, run `serverless deploy`. Webpack output will show the schema being moved with `copy-webpack-plugin`: ```terminal serverless package ``` ```terminal no-copy Running "serverless" from node_modules DOTENV: Loading environment variables from .env: - DATABASE_URL Packaging deployment-example-sls for stage dev (us-east-1) asset handlers/posts.js 713 bytes [emitted] [minimized] (name: handlers/posts) asset schema.prisma 293 bytes [emitted] [from: node_modules/.prisma/client/schema.prisma] [copied] ./handlers/posts.ts 745 bytes [built] [code generated] external "@prisma/client" 42 bytes [built] [code generated] webpack 5.88.2 compiled successfully in 685 ms Package lock found - Using locked versions Packing external modules: @prisma/client@^5.1.1 ✔ Service packaged (5s) ``` ## Deploying with SST ### Working with environment variables While SST supports `.env` files, [it is not recommended](https://v2.sst.dev/config#should-i-use-configsecret-or-env-for-secrets). SST recommends using `Config` to access these environment variables in a secure way. The SST guide [available here](https://v2.sst.dev/config#overview) is a step-by-step guide to get started with `Config`. Assuming you have created a new secret called `DATABASE_URL` and have [bound that secret to your app](https://v2.sst.dev/config#bind-the-config), you can set up `PrismaClient` with the following: ```ts file=prisma.ts showLineNumbers import { PrismaClient } from '@prisma/client' import { Config } from 'sst/node/config' const globalForPrisma = global as unknown as { prisma: PrismaClient } export const prisma = globalForPrisma.prisma || new PrismaClient({ datasourceUrl: Config.DATABASE_URL, }) if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma export default prisma ``` --- # Deploy to Netlify URL: https://www.prisma.io/docs/orm/prisma-client/deployment/serverless/deploy-to-netlify This guide covers the steps you will need to take in order to deploy your application that uses Prisma ORM to [Netlify](https://www.netlify.com/). Netlify is a cloud platform for continuous deployment, static sites, and serverless functions. Netlify integrates seamlessly with GitHub for automatic deployments upon commits. When you follow the steps below, you will use that approach to create a CI/CD pipeline that deploys your application from a GitHub repository. ## Prerequisites Before you can follow this guide, you will need to set up your application to begin deploying to Netlify. We recommend the ["Get started with Netlify"](https://docs.netlify.com/get-started/) guide for a quick overview and ["Deploy functions"](https://docs.netlify.com/functions/deploy/?fn-language=ts) for an in-depth look at your deployment options. ## Binary targets in `schema.prisma` Since your code is being deployed to Netlify's environment, which isn't necessarily the same as your development environment, you will need to set [`binaryTargets`](/orm/reference/prisma-schema-reference#binarytargets-options) in order to download the query engine that is compatible with the Netlify runtime during your build step. If you do not set this option, your deployed code will have an incorrect query engine deployed with it and will not function. Depending on the version of Node.js, your Prisma schema should contain either `rhel-openssl-1.0.x` or `rhel-openssl-3.0.x` in the `generator` block: ```prisma binaryTargets = ["native", "rhel-openssl-1.0.x"] ``` ```prisma binaryTargets = ["native", "rhel-openssl-3.0.x"] ``` ## Store environment variables in Netlify We recommend keeping `.env` files in your `.gitignore` in order to prevent leakage of sensitives connection strings. Instead, you can use the Netlify CLI to [import values into netlify directly](https://docs.netlify.com/environment-variables/get-started/#import-variables-with-the-netlify-cli). Assuming you have a file like the following: ```bash file=.env # Connect to DB DATABASE_URL="postgresql://postgres:__PASSWORD__@__HOST__:__PORT__/__DB_NAME__" ``` You can upload the file as environment variables using the `env:import` command: ```terminal no-break-terminal netlify env:import .env ``` ```no-break-terminal site: my-very-very-cool-site ---------------------------------------------------------------------------------. Imported environment variables | ---------------------------------------------------------------------------------| Key | Value | --------------|------------------------------------------------------------------| DATABASE_URL | postgresql://postgres:__PASSWORD__@__HOST__:__PORT__/__DB_NAME__ | ---------------------------------------------------------------------------------' ```
If you are not using an `.env` file If you are storing your database connection string and other environment variables in a different method, you will need to manually upload your environment variables to Netlify. These options are [discussed in Netlfiy's documentation](https://docs.netlify.com/environment-variables/get-started/) and one method, uploading via the UI, is described below. 1. Open the Netlify admin UI for the site. You can use Netlify CLI as follows: ```terminal netlify open --admin ``` 2. Click **Site settings**: ![Netlify admin UI](./images/500-06-deploy-to-netlify-site-settings.png) 3. Navigate to **Build & deploy** in the sidebar on the left and select **Environment**. 4. Click **Edit variables** and create a variable with the key `DATABASE_URL` and set its value to your database connection string. ![Netlify environment variables](./images/500-07-deploy-to-netlify-environment-variables-settings.png) 5. Click **Save**.
Now start a new Netlify build and deployment so that the new build can use the newly uploaded environment variables. ```terminal netlify deploy ``` You can now test the deployed application. ## Connection pooling When you use a Function-as-a-Service provider, like Netlify, it is beneficial to pool database connections for performance reasons. This is because every function invocation may result in a new connection to your database which can quickly run out of open connections. You can use [Accelerate](/accelerate) for connection pooling or [Prisma Postgres](/postgres), which has built-in connection pooling, to reduce your Prisma Client bundle size, and to avoid cold starts. For more information on connection management for serverless environments, refer to our [connection management guide](/orm/prisma-client/setup-and-configuration/databases-connections#serverless-environments-faas). --- # Serverless functions URL: https://www.prisma.io/docs/orm/prisma-client/deployment/serverless/index If your application is deployed via a "Serverless Function" or "Function-as-a-Service (FaaS)" offering and uses a standard Node.js runtime, it is a serverless app. Common deployment examples include [AWS Lambda](/orm/prisma-client/deployment/serverless/deploy-to-aws-lambda) and [Vercel Serverless Functions](/orm/prisma-client/deployment/serverless/deploy-to-vercel). ## Guides for Serverless Function providers --- # Deploying edge functions with Prisma ORM URL: https://www.prisma.io/docs/orm/prisma-client/deployment/edge/overview You can deploy an application that uses Prisma ORM to the edge. Depending on which edge function provider and which database you use, there are different considerations and things to be aware of. Here is a brief overview of all the edge function providers that are currently supported by Prisma ORM: | Provider / Product | Supported natively with Prisma ORM | Supported with Prisma Postgres (and Prisma Accelerate)| | ---------------------- | ------------------------------------------------------- | -------------------------------- | | Vercel Edge Functions | ✅ (Preview; only compatible drivers) | ✅ | | Vercel Edge Middleware | ✅ (Preview; only compatible drivers) | ✅ | | Cloudflare Workers | ✅ (Preview; only compatible drivers) | ✅ | | Cloudflare Pages | ✅ (Preview; only compatible drivers) | ✅ | | Deno Deploy | [Not yet](https://github.com/prisma/prisma/issues/2452) | ✅ | Deploying edge functions that use Prisma ORM on Cloudflare and Vercel is currently in [Preview](/orm/more/releases#preview). ## Edge-compatibility of database drivers ### Why are there limitations around database drivers in edge functions? Edge functions typically don't use the standard Node.js runtime. For example, Vercel Edge Functions and Cloudflare Workers are running code in [V8 isolates](https://v8docs.nodesource.com/node-0.8/d5/dda/classv8_1_1_isolate.html). Deno Deploy is using the [Deno](https://deno.com/) JavaScript runtime. As a consequence, these edge functions only have access to a small subset of the standard Node.js APIs and also have constrained computing resources (CPU and memory). In particular, the constraint of not being able to freely open TCP connections makes it difficult to talk to a traditional database from an edge function. While Cloudflare has introduced a [`connect()`](https://developers.cloudflare.com/workers/runtime-apis/tcp-sockets/) API that enables limited TCP connections, this still only enables database access using specific database drivers that are compatible with that API. :::note We recommend using [Prisma Postgres](/postgres). It is fully supported on edge runtimes and does not require a specialized edge-compatible driver. For other databases, [Prisma Accelerate](/accelerate) extends edge compatibility so you can connect to _any_ database from _any_ edge function provider. ::: ### Which database drivers are edge-compatible? Here is an overview of the different database drivers and their compatibility with different edge function offerings: - [Neon Serverless](https://neon.tech/docs/serverless/serverless-driver) uses HTTP to access the database. It works with Cloudflare Workers and Vercel Edge Functions. - [PlanetScale Serverless](https://planetscale.com/docs/tutorials/planetscale-serverless-driver) uses HTTP to access the database. It works with Cloudflare Workers and Vercel Edge Functions. - [`node-postgres`](https://node-postgres.com/) (`pg`) uses Cloudflare's `connect()` (TCP) to access the database. It is only compatible with Cloudflare Workers, not with Vercel Edge Functions. - [`@libsql/client`](https://github.com/tursodatabase/libsql-client-ts) is used to access Turso databases. It works with Cloudflare Workers and Vercel Edge Functions. - [Cloudflare D1](https://developers.cloudflare.com/d1/) is used to access D1 databases. It is only compatible with Cloudflare Workers, not with Vercel Edge Functions. - [Prisma Postgres](/postgres) is used to access a PostgreSQL database built on bare-metal using unikernels. It is supported on both Cloudflare Workers and Vercel. There's [also work being done](https://github.com/sidorares/node-mysql2/pull/2289) on the `node-mysql2` driver which will enable access to traditional MySQL databases from Cloudflare Workers and Pages in the future as well. You can use all of these drivers with Prisma ORM using the respective [driver adapters](/orm/overview/databases/database-drivers). Depending on which deployment provider and database/driver you use, there may be special considerations. Please take a look at the deployment docs for your respective scenario to make sure you can deploy your application successfully: - Cloudflare - [PostgreSQL (traditional)](/orm/prisma-client/deployment/edge/deploy-to-cloudflare#postgresql-traditional) - [PlanetScale](/orm/prisma-client/deployment/edge/deploy-to-cloudflare#planetscale) - [Neon](/orm/prisma-client/deployment/edge/deploy-to-cloudflare#neon) - [Cloudflare D1](/guides/cloudflare-d1) - [Prisma Postgres](https://developers.cloudflare.com/workers/tutorials/using-prisma-postgres-with-workers) - Vercel - [Vercel Postgres](/orm/prisma-client/deployment/edge/deploy-to-vercel#vercel-postgres) - [Neon](/orm/prisma-client/deployment/edge/deploy-to-vercel#neon) - [PlanetScale](/orm/prisma-client/deployment/edge/deploy-to-vercel#planetscale) - [Prisma Postgres](/guides/nextjs) If you want to deploy an app using Turso, you can follow the instructions [here](/orm/overview/databases/turso). --- # Deploy to Cloudflare Workers & Pages URL: https://www.prisma.io/docs/orm/prisma-client/deployment/edge/deploy-to-cloudflare This page covers everything you need to know to deploy an app with Prisma ORM to a [Cloudflare Worker](https://developers.cloudflare.com/workers/) or to [Cloudflare Pages](https://developers.cloudflare.com/pages). ## General considerations when deploying to Cloudflare Workers This section covers _general_ things you need to be aware of when deploying to Cloudflare Workers or Pages and are using Prisma ORM, regardless of the database provider you use. ### Using Prisma Postgres You can use Prisma Postgres and deploy to Cloudflare Workers. After you create a Worker, run: ```terminal npx prisma@latest init --db ``` Enter a name for your project and choose a database region. This command: - Connects your CLI to your [Prisma Data Platform](https://console.prisma.io) account. If you're not logged in or don't have an account, your browser will open to guide you through creating a new account or signing into your existing one. - Creates a `prisma` directory containing a `schema.prisma` file for your database models. - Creates a `.env` file with your `DATABASE_URL` (e.g., for Prisma Postgres it should have something similar to `DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI..."`). You'll need to install the Client extension required to use Prisma Postgres: ```terminal npm i @prisma/extension-accelerate ``` And extend `PrismaClient` with the extension in your application code: ```typescript import { PrismaClient } from "@prisma/client/edge"; import { withAccelerate } from "@prisma/extension-accelerate"; export interface Env { DATABASE_URL: string; } export default { async fetch(request, env, ctx) { const prisma = new PrismaClient({ datasourceUrl: env.DATABASE_URL, }).$extends(withAccelerate()); const users = await prisma.user.findMany(); const result = JSON.stringify(users); return new Response(result); }, } satisfies ExportedHandler; ``` Then setup helper scripts to perform migrations and generate `PrismaClient` as [shown in this section](/orm/prisma-client/deployment/edge/deploy-to-cloudflare#development). :::note You need to have the `dotenv-cli` package installed as Cloudflare Workers does not support `.env` files. You can do this by running the following command to install the package locally in your project: `npm install -D dotenv-cli`. ::: ### Using an edge-compatible driver When deploying a Cloudflare Worker that uses Prisma ORM, you need to use an [edge-compatible driver](/orm/prisma-client/deployment/edge/overview#edge-compatibility-of-database-drivers) and its respective [driver adapter](/orm/overview/databases/database-drivers#driver-adapters) for Prisma ORM. The edge-compatible drivers for Cloudflare Workers and Pages are: - [Neon Serverless](https://neon.tech/docs/serverless/serverless-driver) uses HTTP to access the database - [PlanetScale Serverless](https://planetscale.com/docs/tutorials/planetscale-serverless-driver) uses HTTP to access the database - [`node-postgres`](https://node-postgres.com/) (`pg`) uses Cloudflare's `connect()` (TCP) to access the database - [`@libsql/client`](https://github.com/tursodatabase/libsql-client-ts) is used to access Turso databases via HTTP - [Cloudflare D1](/orm/prisma-client/deployment/edge/deploy-to-cloudflare) is used to access D1 databases There's [also work being done](https://github.com/sidorares/node-mysql2/pull/2289) on the `node-mysql2` driver which will enable access to traditional MySQL databases from Cloudflare Workers and Pages in the future as well. :::note If your application uses PostgreSQL, we recommend using [Prisma Postgres](/postgres). It is fully supported on edge runtimes and does not require a specialized edge-compatible driver. For other databases, [Prisma Accelerate](/accelerate) extends edge compatibility so you can connect to _any_ database from _any_ edge function provider. ::: ### Setting your database connection URL as an environment variable First, ensure that the `DATABASE_URL` is set as the `url` of the `datasource` in your Prisma schema: ```prisma datasource db { provider = "postgresql" // this might also be `mysql` or another value depending on your database url = env("DATABASE_URL") } ``` #### Development When using your Worker in **development**, you can configure your database connection via the [`.dev.vars` file](https://developers.cloudflare.com/workers/configuration/secrets/#local-development-with-secrets) locally. Assuming you use the `DATABASE_URL` environment variable from above, you can set it inside `.dev.vars` as follows: ```bash file=.dev.vars DATABASE_URL="your-database-connection-string" ``` In the above snippet, `your-database-connection-string` is a placeholder that you need to replace with the value of your own connection string, for example: ```bash file=.dev.vars DATABASE_URL="postgresql://admin:mypassword42@somehost.aws.com:5432/mydb" ``` Note that the `.dev.vars` file is not compatible with `.env` files which are typically used by Prisma ORM. This means that you need to make sure that Prisma ORM gets access to the environment variable when needed, e.g. when running a Prisma CLI command like `prisma migrate dev`. There are several options for achieving this: - Run your Prisma CLI commands using [`dotenv`](https://www.npmjs.com/package/dotenv-cli) to specify from where the CLI should read the environment variable, for example: ```terminal dotenv -e .dev.vars -- npx prisma migrate dev ``` - Create a script in `package.json` that reads `.dev.vars` via [`dotenv`](https://www.npmjs.com/package/dotenv-cli). You can then execute `prisma` commands as follows: `npm run env -- npx prisma migrate dev`. Here's a reference for the script: ```js file=package.json "scripts": { "env": "dotenv -e .dev.vars" } ``` - Duplicate the `DATABASE_URL` and any other relevant env vars into a new file called `.env` which can then be used by Prisma ORM. :::note If you're using an approach that requires `dotenv`, you need to have the [`dotenv-cli`](https://www.npmjs.com/package/dotenv-cli) package installed. You can do this e.g. by using this command to install the package locally in your project: `npm install -D dotenv-cli`. ::: #### Production When deploying your Worker to **production**, you'll need to set the database connection using the `wrangler` CLI: ```terminal npx wrangler secret put DATABASE_URL ``` The command is interactive and will ask you to enter the value for the `DATABASE_URL` env var as the next step in the terminal. :::note This command requires you to be authenticated, and will ask you to log in to your Cloudflare account in case you are not. ::: ### Size limits on free accounts Cloudflare has a [size limit of 3 MB for Workers on the free plan](https://developers.cloudflare.com/workers/platform/limits/). If your application bundle with Prisma ORM exceeds that size, we recommend upgrading to a paid Worker plan or using Prisma Accelerate to deploy your application. If you're running into this problem with `pg` and the `@prisma/adapter-pg` package, you can replace the `pg` with the custom [`@prisma/pg-worker`](https://github.com/prisma/prisma/tree/main/packages/pg-worker) package and use the [`@prisma/adapter-pg-worker`](https://github.com/prisma/prisma/tree/main/packages/adapter-pg-worker) adapter that belongs to it. `@prisma/pg-worker` is an optimized and lightweight version of `pg` that is designed to be used in a Worker. It is a drop-in replacement for `pg` and is fully compatible with Prisma ORM. ### Deploying a Next.js app to Cloudflare Pages with `@cloudflare/next-on-pages` Cloudflare offers an option to run Next.js apps on Cloudflare Pages with [`@cloudflare/next-on-pages`](https://github.com/cloudflare/next-on-pages), see the [docs](https://developers.cloudflare.com/pages/framework-guides/nextjs/ssr/get-started/) for instructions. Based on some testing, we found the following: - You can deploy using the PlanetScale or Neon Serverless Driver. - Traditional PostgreSQL deployments using `pg` don't work because `pg` itself currently does not work with `@cloudflare/next-on-pages` (see [here](https://github.com/cloudflare/next-on-pages/issues/605)). Feel free to reach out to us on [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=inline_text) if you find that anything has changed about this. ### Set `PRISMA_CLIENT_FORCE_WASM=1` when running locally with `node` Some frameworks (e.g. [hono](https://hono.dev/)) use `node` instead of `wrangler` for running Workers locally. If you're using such a framework or are running your Worker locally with `node` for another reason, you need to set the `PRISMA_CLIENT_FORCE_WASM` environment variable: ``` export PRISMA_CLIENT_FORCE_WASM=1 ``` ## Database-specific considerations & examples This section provides database-specific instructions for deploying a Cloudflare Worker with Prisma ORM. ### Prerequisites As a prerequisite for the following section, you need to have a Cloudflare Worker running locally and the Prisma CLI installed. If you don't have that yet, you can run these commands: ```terminal npm create cloudflare@latest prisma-cloudflare-worker-example -- --type hello-world cd prisma-cloudflare-worker-example npm install prisma --save-dev npx prisma init --output ../generated/prisma ``` You'll further need a database instance of your database provider of choice available. Refer to the respective documentation of the provider for setting up that instance. We'll use the default `User` model for the example below: ```prisma model User { id Int @id @default(autoincrement()) email String @unique name String? } ``` ### PostgreSQL (traditional) If you are using a traditional PostgreSQL database that's accessed via TCP and the `pg` driver, you need to: - use the `@prisma/adapter-pg` database adapter (via the `driverAdapters` Preview feature) - set `node_compat = true` in `wrangler.toml` (see the [Cloudflare docs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/)) If you are running into a size issue and can't deploy your application because of that, you can use our slimmer variant of the `pg` driver package [`@prisma/pg-worker`](https://github.com/prisma/prisma/tree/main/packages/pg-worker) and the [`@prisma/adapter-pg-worker`](https://github.com/prisma/prisma/tree/main/packages/adapter-pg-worker) adapter that belongs to it. `@prisma/pg-worker` is an optimized and lightweight version of `pg` that is designed to be used in a Worker. It is a drop-in replacement for `pg` and is fully compatible with Prisma ORM. #### 1. Configure Prisma schema & database connection :::note If you don't have a project to deploy, follow the instructions in the [Prerequisites](#prerequisites) to bootstrap a basic Cloudflare Worker with Prisma ORM in it. ::: First, ensure that the database connection is configured properly. In your Prisma schema, set the `url` of the `datasource` block to the `DATABASE_URL` environment variable. You also need to enable the `driverAdapters` feature flag: ```prisma file=schema.prisma generator client { provider = "prisma-client-js" previewFeatures = ["driverAdapters"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` Next, you need to set the `DATABASE_URL` environment variable to the value of your database connection string. You'll do this in a file called `.dev.vars` used by Cloudflare: ```bash file=.dev.vars DATABASE_URL="postgresql://admin:mypassword42@somehost.aws.com:5432/mydb" ``` Because the Prisma CLI by default is only compatible with `.env` files, you can adjust your `package.json` with the following script that loads the env vars from `.dev.vars`. You can then use this script to load the env vars before executing a `prisma` command. Add this script to your `package.json`: ```js file=package.json highlight=5;add { // ... "scripts": { // .... "env": "dotenv -e .dev.vars" }, // ... } ``` Now you can execute Prisma CLI commands as follows while ensuring that the command has access to the env vars in `.dev.vars`: ```terminal npm run env -- npx prisma ``` #### 2. Install dependencies Next, install the required packages: ```terminal npm install @prisma/adapter-pg ``` #### 3. Set `node_compat = true` in `wrangler.toml` In your `wrangler.toml` file, add the following line: ```toml file=wrangler.toml node_compat = true ``` :::note For Cloudflare Pages, using `node_compat` is not officially supported. If you want to use `pg` in Cloudflare Pages, you can find a workaround [here](https://github.com/cloudflare/workers-sdk/pull/2541#issuecomment-1954209855). ::: #### 4. Migrate your database schema (if applicable) If you ran `npx prisma init` above, you need to migrate your database schema to create the `User` table that's defined in your Prisma schema (if you already have all the tables you need in your database, you can skip this step): ```terminal npm run env -- npx prisma migrate dev --name init ``` #### 5. Use Prisma Client in your Worker to send a query to the database Here is a sample code snippet that you can use to instantiate `PrismaClient` and send a query to your database: ```ts import { PrismaClient } from '@prisma/client' import { PrismaPg } from '@prisma/adapter-pg' export default { async fetch(request, env, ctx) { const adapter = new PrismaPg({ connectionString: env.DATABASE_URL }) const prisma = new PrismaClient({ adapter }) const users = await prisma.user.findMany() const result = JSON.stringify(users) return new Response(result) }, } ``` #### 6. Run the Worker locally To run the Worker locally, you can run the `wrangler dev` command: ```terminal npx wrangler dev ``` #### 7. Set the `DATABASE_URL` environment variable and deploy the Worker To deploy the Worker, you first need to the `DATABASE_URL` environment variable [via the `wrangler` CLI](https://developers.cloudflare.com/workers/configuration/secrets/#secrets-on-deployed-workers): ```terminal npx wrangler secret put DATABASE_URL ``` The command is interactive and will ask you to enter the value for the `DATABASE_URL` env var as the next step in the terminal. :::note This command requires you to be authenticated, and will ask you to log in to your Cloudflare account in case you are not. ::: Then you can go ahead then deploy the Worker: ```terminal npx wrangler deploy ``` The command will output the URL where you can access the deployed Worker. ### PlanetScale If you are using a PlanetScale database, you need to: - use the `@prisma/adapter-planetscale` database adapter (via the `driverAdapters` Preview feature) - manually remove the conflicting `cache` field ([learn more]()): ```ts export default { async fetch(request, env, ctx) { const adapter = new PrismaPlanetScale({ url: env.DATABASE_URL, // see https://github.com/cloudflare/workerd/issues/698 fetch(url, init) { delete init['cache'] return fetch(url, init) }, }) const prisma = new PrismaClient({ adapter }) // ... }, } ``` #### 1. Configure Prisma schema & database connection :::note If you don't have a project to deploy, follow the instructions in the [Prerequisites](#prerequisites) to bootstrap a basic Cloudflare Worker with Prisma ORM in it. ::: First, ensure that the database connection is configured properly. In your Prisma schema, set the `url` of the `datasource` block to the `DATABASE_URL` environment variable. You also need to enable the `driverAdapters` feature flag: ```prisma file=schema.prisma generator client { provider = "prisma-client-js" previewFeatures = ["driverAdapters"] } datasource db { provider = "mysql" url = env("DATABASE_URL") relationMode = "prisma" // required for PlanetScale (as by default foreign keys are disabled) } ``` Next, you need to set the `DATABASE_URL` environment variable to the value of your database connection string. You'll do this in a file called `.dev.vars` used by Cloudflare: ```bash file=.dev.vars DATABASE_URL="mysql://32qxa2r7hfl3102wrccj:password@us-east.connect.psdb.cloud/demo-cf-worker-ps?sslaccept=strict" ``` Because the Prisma CLI by default is only compatible with `.env` files, you can adjust your `package.json` with the following script that loads the env vars from `.dev.vars`. You can then use this script to load the env vars before executing a `prisma` command. Add this script to your `package.json`: ```js file=package.json highlight=5;add { // ... "scripts": { // .... "env": "dotenv -e .dev.vars" }, // ... } ``` Now you can execute Prisma CLI commands as follows while ensuring that the command has access to the env vars in `.dev.vars`: ```terminal npm run env -- npx prisma ``` #### 2. Install dependencies Next, install the required packages: ```terminal npm install @prisma/adapter-planetscale ``` #### 3. Migrate your database schema (if applicable) If you ran `npx prisma init` above, you need to migrate your database schema to create the `User` table that's defined in your Prisma schema (if you already have all the tables you need in your database, you can skip this step): ```terminal npm run env -- npx prisma db push ``` #### 4. Use Prisma Client in your Worker to send a query to the database Here is a sample code snippet that you can use to instantiate `PrismaClient` and send a query to your database: ```ts import { PrismaClient } from '@prisma/client' import { PrismaPlanetScale } from '@prisma/adapter-planetscale' export default { async fetch(request, env, ctx) { const adapter = new PrismaPlanetScale({ url: env.DATABASE_URL, // see https://github.com/cloudflare/workerd/issues/698 fetch(url, init) { delete init['cache'] return fetch(url, init) }, }) const prisma = new PrismaClient({ adapter }) const users = await prisma.user.findMany() const result = JSON.stringify(users) return new Response(result) }, } ``` #### 6. Run the Worker locally To run the Worker locally, you can run the `wrangler dev` command: ```terminal npx wrangler dev ``` #### 7. Set the `DATABASE_URL` environment variable and deploy the Worker To deploy the Worker, you first need to the `DATABASE_URL` environment variable [via the `wrangler` CLI](https://developers.cloudflare.com/workers/configuration/secrets/#secrets-on-deployed-workers): ```terminal npx wrangler secret put DATABASE_URL ``` The command is interactive and will ask you to enter the value for the `DATABASE_URL` env var as the next step in the terminal. :::note This command requires you to be authenticated, and will ask you to log in to your Cloudflare account in case you are not. ::: Then you can go ahead then deploy the Worker: ```terminal npx wrangler deploy ``` The command will output the URL where you can access the deployed Worker. ### Neon If you are using a Neon database, you need to: - use the `@prisma/adapter-neon` database adapter (via the `driverAdapters` Preview feature) #### 1. Configure Prisma schema & database connection :::note If you don't have a project to deploy, follow the instructions in the [Prerequisites](#prerequisites) to bootstrap a basic Cloudflare Worker with Prisma ORM in it. ::: First, ensure that the database connection is configured properly. In your Prisma schema, set the `url` of the `datasource` block to the `DATABASE_URL` environment variable. You also need to enable the `driverAdapters` feature flag: ```prisma file=schema.prisma generator client { provider = "prisma-client-js" previewFeatures = ["driverAdapters"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` Next, you need to set the `DATABASE_URL` environment variable to the value of your database connection string. You'll do this in a file called `.dev.vars` used by Cloudflare: ```bash file=.dev.vars DATABASE_URL="postgresql://janedoe:password@ep-nameless-pond-a23b1mdz.eu-central-1.aws.neon.tech/neondb?sslmode=require" ``` Because the Prisma CLI by default is only compatible with `.env` files, you can adjust your `package.json` with the following script that loads the env vars from `.dev.vars`. You can then use this script to load the env vars before executing a `prisma` command. Add this script to your `package.json`: ```js file=package.json highlight=5;add { // ... "scripts": { // .... "env": "dotenv -e .dev.vars" }, // ... } ``` Now you can execute Prisma CLI commands as follows while ensuring that the command has access to the env vars in `.dev.vars`: ```terminal npm run env -- npx prisma ``` #### 2. Install dependencies Next, install the required packages: ```terminal npm install @prisma/adapter-neon ``` #### 3. Migrate your database schema (if applicable) If you ran `npx prisma init` above, you need to migrate your database schema to create the `User` table that's defined in your Prisma schema (if you already have all the tables you need in your database, you can skip this step): ```terminal npm run env -- npx prisma migrate dev --name init ``` #### 5. Use Prisma Client in your Worker to send a query to the database Here is a sample code snippet that you can use to instantiate `PrismaClient` and send a query to your database: ```ts import { PrismaClient } from '@prisma/client' import { PrismaNeon } from '@prisma/adapter-neon' export default { async fetch(request, env, ctx) { const adapter = new PrismaNeon({ connectionString: env.DATABASE_URL }) const prisma = new PrismaClient({ adapter }) const users = await prisma.user.findMany() const result = JSON.stringify(users) return new Response(result) }, } ``` #### 6. Run the Worker locally To run the Worker locally, you can run the `wrangler dev` command: ```terminal npx wrangler dev ``` #### 7. Set the `DATABASE_URL` environment variable and deploy the Worker To deploy the Worker, you first need to the `DATABASE_URL` environment variable [via the `wrangler` CLI](https://developers.cloudflare.com/workers/configuration/secrets/#secrets-on-deployed-workers): ```terminal npx wrangler secret put DATABASE_URL ``` The command is interactive and will ask you to enter the value for the `DATABASE_URL` env var as the next step in the terminal. :::note This command requires you to be authenticated, and will ask you to log in to your Cloudflare account in case you are not. ::: Then you can go ahead then deploy the Worker: ```terminal npx wrangler deploy ``` The command will output the URL where you can access the deployed Worker. --- # Deploy to Vercel Edge Functions & Middleware URL: https://www.prisma.io/docs/orm/prisma-client/deployment/edge/deploy-to-vercel This page covers everything you need to know to deploy an app that uses Prisma Client for talking to a database in [Vercel Edge Middleware](https://vercel.com/docs/functions/edge-middleware) or a [Vercel Function](https://vercel.com/docs/functions) deployed to the [Vercel Edge Runtime](https://vercel.com/docs/functions/runtimes/edge-runtime). To deploy a Vercel Function to the Vercel Edge Runtime, you can set `export const runtime = 'edge'` outside the request handler of the Vercel Function. ## General considerations when deploying to Vercel Edge Functions & Edge Middleware ### Using Prisma Postgres You can use Prisma Postgres in Vercel's edge runtime. Follow this guide for an end-to-end tutorial on [deploying an application to Vercel using Prisma Postgres](/guides/nextjs). ### Using an edge-compatible driver Vercel's Edge Runtime currently only supports a limited set of database drivers: - [Neon Serverless](https://neon.tech/docs/serverless/serverless-driver) uses HTTP to access the database (also compatible with [Vercel Postgres](https://vercel.com/docs/storage/vercel-postgres)) - [PlanetScale Serverless](https://planetscale.com/docs/tutorials/planetscale-serverless-driver) uses HTTP to access the database - [`@libsql/client`](https://github.com/tursodatabase/libsql-client-ts) is used to access Turso databases Note that [`node-postgres`](https://node-postgres.com/) (`pg`) is currently _not_ supported on Vercel Edge Functions. When deploying a Vercel Edge Function that uses Prisma ORM, you need to use one of these [edge-compatible drivers](/orm/prisma-client/deployment/edge/overview#edge-compatibility-of-database-drivers) and its respective [driver adapter](/orm/overview/databases/database-drivers#driver-adapters) for Prisma ORM. :::note If your application uses PostgreSQL, we recommend using [Prisma Postgres](/postgres). It is fully supported on edge runtimes and does not require a specialized edge-compatible driver. For other databases, [Prisma Accelerate](/accelerate) extends edge compatibility so you can connect to _any_ database from _any_ edge function provider. ::: ### Setting your database connection URL as an environment variable First, ensure that the `DATABASE_URL` is set as the `url` of the `datasource` in your Prisma schema: ```prisma datasource db { provider = "postgresql" // this might also be `mysql` or another value depending on your database url = env("DATABASE_URL") } ``` #### Development When in **development**, you can configure your database connection via the `DATABASE_URL` environment variable (e.g. [using `.env` files](/orm/more/development-environment/environment-variables)). #### Production When deploying your Edge Function to **production**, you'll need to set the database connection using the `vercel` CLI: ```terminal npx vercel env add DATABASE_URL ``` This command is interactive and will ask you to select environments and provide the value for the `DATABASE_URL` in subsequent steps. Alternatively, you can configure the environment variable [via the UI](https://vercel.com/docs/projects/environment-variables#creating-environment-variables) of your project in the Vercel Dashboard. ### Generate Prisma Client in `postinstall` hook In your `package.json`, you should add a `"postinstall"` section as follows: ```js file=package.json showLineNumbers { // ..., "postinstall": "prisma generate" } ``` ### Size limits on free accounts Vercel has a [size limit of 1 MB on free accounts](https://vercel.com/docs/functions/limitations). If your application bundle with Prisma ORM exceeds that size, we recommend upgrading to a paid account or using Prisma Accelerate to deploy your application. ## Database-specific considerations & examples This section provides database-specific instructions for deploying a Vercel Edge Functions with Prisma ORM. ### Prerequisites As a prerequisite for the following section, you need to have a Vercel Edge Function (which typically comes in the form of a Next.js API route) running locally and the Prisma and Vercel CLIs installed. If you don't have that yet, you can run these commands to set up a Next.js app from scratch (following the instructions of the [Vercel Functions Quickstart](https://vercel.com/docs/functions/quickstart)): ```terminal npm install -g vercel npx create-next-app@latest npm install prisma --save-dev npx prisma init --output ../app/generated/prisma ``` We'll use the default `User` model for the example below: ```prisma model User { id Int @id @default(autoincrement()) email String @unique name String? } ``` ### Vercel Postgres If you are using Vercel Postgres, you need to: - use the `@prisma/adapter-neon` database adapter (via the `driverAdapters` Preview feature) because Vercel Postgres uses [Neon](https://neon.tech/) under the hood - be aware that Vercel by default calls the environment variable for the database connection string `POSTGRES_PRISMA_URL` while the default name used in the Prisma docs is typically `DATABASE_URL`; using Vercel's naming, you need to set the following fields on your `datasource` block: ```prisma datasource db { provider = "postgresql" url = env("POSTGRES_PRISMA_URL") // uses connection pooling directUrl = env("POSTGRES_URL_NON_POOLING") // uses a direct connection } ``` #### 1. Configure Prisma schema & database connection :::note If you don't have a project to deploy, follow the instructions in the [Prerequisites](#prerequisites) to bootstrap a basic Next.js app with Prisma ORM in it. ::: First, ensure that the database connection is configured properly. In your Prisma schema, set the `url` of the `datasource` block to the `POSTGRES_PRISMA_URL` and the `directUrl` to the `POSTGRES_URL_NON_POOLING` environment variable. You also need to enable the `driverAdapters` feature flag: ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" previewFeatures = ["driverAdapters"] } datasource db { provider = "postgresql" url = env("POSTGRES_PRISMA_URL") // uses connection pooling directUrl = env("POSTGRES_URL_NON_POOLING") // uses a direct connection } ``` Next, you need to set the `POSTGRES_PRISMA_URL` and `POSTGRES_URL_NON_POOLING` environment variable to the values of your database connection. If you ran `npx prisma init`, you can use the `.env` file that was created by this command to set these: ```bash file=.env showLineNumbers POSTGRES_PRISMA_URL="postgres://user:password@host-pooler.region.postgres.vercel-storage.com:5432/name?pgbouncer=true&connect_timeout=15" POSTGRES_URL_NON_POOLING="postgres://user:password@host.region.postgres.vercel-storage.com:5432/name" ``` #### 2. Install dependencies Next, install the required packages: ```terminal npm install @prisma/adapter-neon ``` #### 3. Configure `postinstall` hook Next, add a new key to the `scripts` section in your `package.json`: ```js file=package.json { // ... "scripts": { // ... //add-next-line "postinstall": "prisma generate" } } ``` #### 4. Migrate your database schema (if applicable) If you ran `npx prisma init` above, you need to migrate your database schema to create the `User` table that's defined in your Prisma schema (if you already have all the tables you need in your database, you can skip this step): ```terminal npx prisma migrate dev --name init ``` #### 5. Use Prisma Client in your Vercel Edge Function to send a query to the database If you created the project from scratch, you can create a new edge function as follows. First, create a new API route, e.g. by using these commands: ```terminal mkdir src/app/api mkdir src/app/api/edge touch src/app/api/edge/route.ts ``` Here is a sample code snippet that you can use to instantiate `PrismaClient` and send a query to your database in the new `app/api/edge/route.ts` file you just created: ```ts file=app/api/edge/route.ts showLineNumbers import { NextResponse } from 'next/server' import { PrismaClient } from '@prisma/client' import { PrismaNeon } from '@prisma/adapter-neon' export const runtime = 'edge' export async function GET(request: Request) { const adapter = new PrismaNeon({ connectionString: process.env.POSTGRES_PRISMA_URL }) const prisma = new PrismaClient({ adapter }) const users = await prisma.user.findMany() return NextResponse.json(users, { status: 200 }) } ``` #### 6. Run the Edge Function locally Run the app with the following command: ```terminal npm run dev ``` You can now access the Edge Function via this URL: [`http://localhost:3000/api/edge`](http://localhost:3000/api/edge). #### 7. Set the `POSTGRES_PRISMA_URL` environment variable and deploy the Edge Function Run the following command to deploy your project with Vercel: ```terminal npx vercel deploy ``` Note that once the project was created on Vercel, you will need to set the `POSTGRES_PRISMA_URL` environment variable (and if this was your first deploy, it likely failed). You can do this either via the Vercel UI or by running the following command: ``` npx vercel env add POSTGRES_PRISMA_URL ``` At this point, you can get the URL of the deployed application from the Vercel Dashboard and access the edge function via the `/api/edge` route. ### PlanetScale If you are using a PlanetScale database, you need to: - use the `@prisma/adapter-planetscale` database adapter (via the `driverAdapters` Preview feature) #### 1. Configure Prisma schema & database connection :::note If you don't have a project to deploy, follow the instructions in the [Prerequisites](#prerequisites) to bootstrap a basic Next.js app with Prisma ORM in it. ::: First, ensure that the database connection is configured properly. In your Prisma schema, set the `url` of the `datasource` block to the `DATABASE_URL` environment variable. You also need to enable the `driverAdapters` feature flag: ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" previewFeatures = ["driverAdapters"] } datasource db { provider = "mysql" url = env("DATABASE_URL") relationMode = "prisma" // required for PlanetScale (as by default foreign keys are disabled) } ``` Next, you need to set the `DATABASE_URL` environment variable in your `.env` file that's used both by Prisma and Next.js to read your env vars: ```bash file=.env DATABASE_URL="mysql://32qxa2r7hfl3102wrccj:password@us-east.connect.psdb.cloud/demo-cf-worker-ps?sslaccept=strict" ``` #### 2. Install dependencies Next, install the required packages: ```terminal npm install @prisma/adapter-planetscale ``` #### 3. Configure `postinstall` hook Next, add a new key to the `scripts` section in your `package.json`: ```js file=package.json { // ... "scripts": { // ... //add-next-line "postinstall": "prisma generate" } } ``` #### 4. Migrate your database schema (if applicable) If you ran `npx prisma init` above, you need to migrate your database schema to create the `User` table that's defined in your Prisma schema (if you already have all the tables you need in your database, you can skip this step): ```terminal npx prisma db push ``` #### 5. Use Prisma Client in an Edge Function to send a query to the database If you created the project from scratch, you can create a new edge function as follows. First, create a new API route, e.g. by using these commands: ```terminal mkdir src/app/api mkdir src/app/api/edge touch src/app/api/edge/route.ts ``` Here is a sample code snippet that you can use to instantiate `PrismaClient` and send a query to your database in the new `app/api/edge/route.ts` file you just created: ```ts file=app/api/edge/route.ts showLineNumbers import { NextResponse } from 'next/server' import { PrismaClient } from '@prisma/client' import { PrismaPlanetScale } from '@prisma/adapter-planetscale' export const runtime = 'edge' export async function GET(request: Request) { const adapter = new PrismaPlanetScale({ url: process.env.DATABASE_URL }) const prisma = new PrismaClient({ adapter }) const users = await prisma.user.findMany() return NextResponse.json(users, { status: 200 }) } ``` #### 6. Run the Edge Function locally Run the app with the following command: ```terminal npm run dev ``` You can now access the Edge Function via this URL: [`http://localhost:3000/api/edge`](http://localhost:3000/api/edge). #### 7. Set the `DATABASE_URL` environment variable and deploy the Edge Function Run the following command to deploy your project with Vercel: ```terminal npx vercel deploy ``` Note that once the project was created on Vercel, you will need to set the `DATABASE_URL` environment variable (and if this was your first deploy, it likely failed). You can do this either via the Vercel UI or by running the following command: ``` npx vercel env add DATABASE_URL ``` At this point, you can get the URL of the deployed application from the Vercel Dashboard and access the edge function via the `/api/edge` route. ### Neon If you are using a Neon database, you need to: - use the `@prisma/adapter-neon` database adapter (via the `driverAdapters` Preview feature) #### 1. Configure Prisma schema & database connection :::note If you don't have a project to deploy, follow the instructions in the [Prerequisites](#prerequisites) to bootstrap a basic Next.js app with Prisma ORM in it. ::: First, ensure that the database connection is configured properly. In your Prisma schema, set the `url` of the `datasource` block to the `DATABASE_URL` environment variable. You also need to enable the `driverAdapters` feature flag: ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" previewFeatures = ["driverAdapters"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` Next, you need to set the `DATABASE_URL` environment variable in your `.env` file that's used both by Prisma and Next.js to read your env vars: ```bash file=.env showLineNumbers DATABASE_URL="postgresql://janedoe:password@ep-nameless-pond-a23b1mdz.eu-central-1.aws.neon.tech/neondb?sslmode=require" ``` #### 2. Install dependencies Next, install the required packages: ```terminal npm install @prisma/adapter-neon ``` #### 3. Configure `postinstall` hook Next, add a new key to the `scripts` section in your `package.json`: ```js file=package.json { // ... "scripts": { // ... //add-next-line "postinstall": "prisma generate" } } ``` #### 4. Migrate your database schema (if applicable) If you ran `npx prisma init` above, you need to migrate your database schema to create the `User` table that's defined in your Prisma schema (if you already have all the tables you need in your database, you can skip this step): ```terminal npx prisma migrate dev --name init ``` #### 5. Use Prisma Client in an Edge Function to send a query to the database If you created the project from scratch, you can create a new edge function as follows. First, create a new API route, e.g. by using these commands: ```terminal mkdir src/app/api mkdir src/app/api/edge touch src/app/api/edge/route.ts ``` Here is a sample code snippet that you can use to instantiate `PrismaClient` and send a query to your database in the new `app/api/edge/route.ts` file you just created: ```ts file=app/api/edge/route.ts showLineNumbers import { NextResponse } from 'next/server' import { PrismaClient } from '@prisma/client' import { PrismaNeon } from '@prisma/adapter-neon' export const runtime = 'edge' export async function GET(request: Request) { const adapter = new PrismaNeon({ connectionString: process.env.DATABASE_URL }) const prisma = new PrismaClient({ adapter }) const users = await prisma.user.findMany() return NextResponse.json(users, { status: 200 }) } ``` #### 6. Run the Edge Function locally Run the app with the following command: ```terminal npm run dev ``` You can now access the Edge Function via this URL: [`http://localhost:3000/api/edge`](http://localhost:3000/api/edge). #### 7. Set the `DATABASE_URL` environment variable and deploy the Edge Function Run the following command to deploy your project with Vercel: ```terminal npx vercel deploy ``` Note that once the project was created on Vercel, you will need to set the `DATABASE_URL` environment variable (and if this was your first deploy, it likely failed). You can do this either via the Vercel UI or by running the following command: ``` npx vercel env add DATABASE_URL ``` At this point, you can get the URL of the deployed application from the Vercel Dashboard and access the edge function via the `/api/edge` route. --- # Deploy to Deno Deploy URL: https://www.prisma.io/docs/orm/prisma-client/deployment/edge/deploy-to-deno-deploy With this guide, you can learn how to build and deploy a simple application to [Deno Deploy](https://deno.com/deploy). The application uses Prisma ORM to save a log of each request to a [Prisma Postgres](/postgres) database. This guide covers the use of Prisma CLI with Deno CLI, Deno Deploy, Prisma Client, and Prisma Postgres. This guide demonstrates how to deploy an application to Deno Deploy in conjunction with a Prisma Postgres database, but you can also use [your own database with Prisma Accelerate](/accelerate/getting-started#prerequisites). ## Prerequisites - a free [Prisma Data Platform](https://console.prisma.io/login) account - a free [Deno Deploy](https://deno.com/deploy) account - Node.js & npm installed - Deno v1.29.4 or later installed. [Learn more](https://docs.deno.com/runtime/#install-deno). - (Recommended) Latest version of Prisma ORM. - (Recommended) Deno extension for VS Code. [Learn more](https://docs.deno.com/runtime/reference/vscode/). ## 1. Set up your application and database To start, you create a directory for your project, and then use `deno run` to initialize your application with `prisma init` as an [npm package with npm specifiers](https://docs.deno.com/runtime/fundamentals/node/). To set up your application, open your terminal and navigate to a location of your choice. Then, run the following commands to set up your application: ```terminal mkdir prisma-deno-deploy cd prisma-deno-deploy deno run --reload -A npm:prisma@latest init --db ``` Enter a name for your project and choose a database region. This command: - Connects your CLI to your [Prisma Data Platform](https://console.prisma.io) account. If you're not logged in or don't have an account, your browser will open to guide you through creating a new account or signing into your existing one. - Creates a `prisma` directory containing a `schema.prisma` file for your database models. - Creates a `.env` file with your `DATABASE_URL` (e.g., for Prisma Postgres it should have something similar to `DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI..."`). Edit the `prisma/schema.prisma` file to define a `Log` model, add a custom `output` path and enable the `deno` preview feature flag: ```prisma file=schema.prisma highlight=3-4,12-23;add showLineNumbers generator client { provider = "prisma-client-js" //add-start previewFeatures = ["deno"] output = "../generated/client" //add-end } datasource db { provider = "postgresql" url = env("DATABASE_URL") } //add-start model Log { id Int @id @default(autoincrement()) level Level message String meta Json } enum Level { Info Warn Error } //add-end ``` :::note To use Deno, you need to add the preview feature flag `deno` to the `generator` block of your `schema.prisma` file. Deno also requires you to generate Prisma Client in a custom location. You can enable this with the `output` parameter in the `generator` block. ::: Then, install [the Client extension](https://www.npmjs.com/package/@prisma/extension-accelerate) required to use Prisma Postgres: ```terminal deno install npm:@prisma/extension-accelerate ``` Prisma Client does not read `.env` files by default on Deno, so you must also install `dotenv-cli` locally: ```terminal deno install npm:dotenv-cli ``` ## 2. Create the database schema With the data model in place and your database connection configured, you can now apply the data model to your database. ```terminal deno run -A npm:prisma migrate dev --name init ``` The command does two things: 1. It creates a new SQL migration file for this migration 1. It runs the SQL migration file against the database At this point, the command has an additional side effects. The command installs Prisma Client and creates the `package.json` file for the project. ## 3. Create your application You can now create a local Deno application. Create `index.ts` in the root folder of your project and add the content below: ```ts file=index.ts import { serve } from "https://deno.land/std@0.140.0/http/server.ts"; import { withAccelerate } from "npm:@prisma/extension-accelerate"; import { PrismaClient } from "./generated/client/deno/edge.ts"; const prisma = new PrismaClient().$extends(withAccelerate()); async function handler(request: Request) { // Ignore /favicon.ico requests: const url = new URL(request.url); if (url.pathname === "/favicon.ico") { return new Response(null, { status: 204 }); } const log = await prisma.log.create({ data: { level: "Info", message: `${request.method} ${request.url}`, meta: { headers: JSON.stringify(request.headers), }, }, }); const body = JSON.stringify(log, null, 2); return new Response(body, { headers: { "content-type": "application/json; charset=utf-8" }, }); } serve(handler); ``` :::info **VS Code error: `An import path cannot end with a '.ts' extension`**

If you use VS Code and see the error `An import path cannot end with a '.ts' extension` for the `import` statements at the beginning of `index.ts`, you need to install the [Deno extension for VS Code](https://docs.deno.com/runtime/reference/vscode/), select **View** > **Command Palette** and run the command **Deno: Initialize Workspace Configuration**. This tells VS Code that the TypeScript files in the current project need to run with Deno, which then triggers the correct validations. ::: ## 4. Test your application locally You can now start your application locally and test the creation of log entries. ```terminal npx dotenv -- deno run -A ./index.ts ``` In a web browser, open [http://localhost:8000/](http://localhost:8000/). This page writes your request to the database. ``` { "id": 1, "level": "Info", "message": "GET http://localhost:8000/", "meta": { "headers": "{}" } } ``` Reload the page a few times.

Every time you reload, the script generates a new log entry and the `id` of the current log entry increments. This confirms that your application works when you run it from your local environment. ## 5. Create a repository and push to GitHub You need a GitHub repository to add your project to Deno Deploy and enable automated deployments whenever you push changes. To set up a GitHub repository: 1. [Create a private GitHub repository](https://github.com/new). 2. Initialize your repository locally and push your changes to GitHub, with the following commands: ```terminal git init -b main git remote add origin https://github.com//prisma-deno-deploy git add . git commit -m "initial commit" git push -u origin main ``` ## 6. Deploy to Deno Deploy Use the GitHub repository to add your application to Deno Deploy: 1. Go to [https://dash.deno.com/](https://dash.deno.com/). 1. Select a GitHub organization or user and then select a repository. 1. Select a production branch and select **Fresh (Automatic)** mode so that Deno Deploy can deploy every time you push a change to the repository. 1. Select `index.ts` as the entry point to your project. 1. Click `Create & Deploy`. The deployment should fail as you have to add the `DATABASE_URL` environment variable. Locate and navigate to the settings for the project. 1. To define the database connection string, click **Add Variable** in the **Environment Variables** section. 1. For **KEY**, enter `DATABASE_URL`. 1. For **VALUE**, paste the database connection string. 1. Click **Save**.
You have to add some code and create another commit to trigger a re-dployment. Add the following code in your `index.ts` file: ```ts file=index.ts import { serve } from "https://deno.land/std@0.140.0/http/server.ts"; import { withAccelerate } from "npm:@prisma/extension-accelerate"; import { PrismaClient } from "./generated/client/deno/edge.ts"; const prisma = new PrismaClient().$extends(withAccelerate()); async function handler(request: Request) { // Ignore /favicon.ico requests: const url = new URL(request.url); if (url.pathname === "/favicon.ico") { return new Response(null, { status: 204 }); } //add-start console.log("Request received.") //add-end const log = await prisma.log.create({ data: { level: "Info", message: `${request.method} ${request.url}`, meta: { headers: JSON.stringify(request.headers), }, }, }); const body = JSON.stringify(log, null, 2); return new Response(body, { headers: { "content-type": "application/json; charset=utf-8" }, }); } serve(handler); ``` Commit the new changes: ```terminal git add . git commit -m "add log" git push origin main ``` This rebuilds the deployment, which now works because the environment variable has been added. After it completes, follow the URL in the deployment output. The application should show the same result as before, with a new, incremented log record ID: ```text { "id": 5, "level": "Info", "message": "GET https://prisma-deno-deploy.deno.dev/", "meta": { "headers": "{}" } } ``` ## Summary You successfully deployed a Deno application that you created in TypeScript, which uses Prisma Client connecting to a Prisma Postgres database. --- # Edge functions URL: https://www.prisma.io/docs/orm/prisma-client/deployment/edge/index If your application is deployed via an "Edge Function" offering or is deployed from a [serverless](/orm/prisma-client/deployment/serverless) offering and has a non-standard runtime, it is a _edge-deployed_ app. Common examples for such offerings include [Cloudflare Workers or Pages](/orm/prisma-client/deployment/edge/deploy-to-cloudflare), [Vercel Edge Functions or Edge Middleware](/orm/prisma-client/deployment/edge/deploy-to-vercel), and [Deno Deploy](/orm/prisma-client/deployment/edge/deploy-to-deno-deploy). ## In this section --- # Module bundlers URL: https://www.prisma.io/docs/orm/prisma-client/deployment/module-bundlers ## Overview _Module bundlers_ bundle JavaScript modules into a single JavaScript file. Most bundlers work by copying over the JavaScript code from a variety of source files into the target file. Since Prisma Client is not only based on JavaScript code, but also relies on the [**query engine binary file**](/orm/more/under-the-hood/engines#the-query-engine-file) to be available, you need to make sure that your bundled code has access to the binary file. To do so, you can use plugins that let you copy over static assets: | Bundler | Plugin | | :---------------------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------- | | Webpack | [`copy-webpack-plugin`](https://github.com/webpack-contrib/copy-webpack-plugin#copy-webpack-plugin) | | Webpack (with [Next.js monorepo](/orm/more/help-and-troubleshooting/nextjs-help#setting-up-prisma-orm-in-a-monorepo)) | [`nextjs-monorepo-workaround-plugin`](https://www.npmjs.com/package/@prisma/nextjs-monorepo-workaround-plugin) | | Parcel | [`parcel-plugin-static-files-copy`](https://github.com/elwin013/parcel-plugin-static-files-copy#readme) | --- # Deploying database changes with Prisma Migrate URL: https://www.prisma.io/docs/orm/prisma-client/deployment/deploy-database-changes-with-prisma-migrate To apply pending migrations to staging, testing, or production environments, run the `migrate deploy` command as part of your CI/CD pipeline: ```terminal npx prisma migrate deploy ``` This guide **does not apply for MongoDB**.
Instead of `migrate deploy`, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb).
Exactly when to run `prisma migrate deploy` depends on your platform. For example, a simplified [Heroku](/orm/prisma-client/deployment/traditional/deploy-to-heroku) workflow includes: 1. Ensuring the `./prisma/migration` folder is in source control 2. Running `prisma migrate deploy` during the [release phase](https://devcenter.heroku.com/articles/release-phase) Ideally, `migrate deploy` should be part of an automated CI/CD pipeline, and we do not generally recommend running this command locally to deploy changes to a production database (for example, by temporarily changing the `DATABASE_URL` environment variable). It is not generally considered good practice to store the production database URL locally. Beware that in order to run the `prisma migrate deploy` command, you need access to the `prisma` dependency that is typically added to the `devDependencies`. Some platforms like Vercel, prune development dependencies during the build, thereby preventing you from calling the command. This can be worked around by making the `prisma` a production dependency, by moving it to `dependencies` in your `package.json`. For more information about the `migrate deploy` command, see: - [`migrate deploy` reference](/orm/reference/prisma-cli-reference#migrate-deploy) - [How `migrate deploy` works](/orm/prisma-migrate/workflows/development-and-production#production-and-testing-environments) - [Production troubleshooting](/orm/prisma-migrate/workflows/patching-and-hotfixing)
## Deploying database changes using GitHub Actions As part of your CI/CD, you can run `prisma migrate deploy` as part of your pipeline to apply pending migrations to your production database. Here is an example action that will run your migrations against your database: ```yaml file=deploy.yml highlight=17-20 showLineNumbers name: Deploy on: push: paths: //highlight-next-line - prisma/migrations/** branches: - main jobs: deploy: runs-on: ubuntu-latest steps: - name: Checkout repo uses: actions/checkout@v3 - name: Setup Node uses: actions/setup-node@v3 - name: Install dependencies run: npm install - name: Apply all pending migrations to the database run: npx prisma migrate deploy env: DATABASE_URL: ${{ secrets.DATABASE_URL }} ``` The highlighted line shows that this action will only run if there is a change in the `prisma/migrations` directory, so `npx prisma migrate deploy` will only run when migrations are updated. Ensure you have the `DATABASE_URL` variable [set as a secret in your repository](https://docs.github.com/en/actions/security-for-github-actions/security-guides/using-secrets-in-github-actions), without quotes around the connection string. --- # Deploy migrations from a local environment URL: https://www.prisma.io/docs/orm/prisma-client/deployment/deploy-migrations-from-a-local-environment There are two scenarios where you might consider deploying migrations directly from a local environment to a production environment. - You have a local CI/CD pipeline - You are [baselining](/orm/prisma-migrate/workflows/baselining) a production environment This page outlines some examples of how you can do that and **why we would generally not recommend it**. ## Local CI/CD pipeline If you do not have an automated CI/CD process, you can technically deploy new migrations from your local environment to production in the following ways: 1. Make sure your migration history is up to date. You can do this through running `prisma migrate dev`, which will generate a migration history from the latest changes made. 2. Swap your local connection URL for your production connection URL ```bash file=.env highlight=1;delete|3;add showLineNumbers //delete-next-line DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/my_local_database" //add-next-line DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/my_production_database" ``` 3. Run `prisma migrate deploy`
⛔{' '} We strongly discourage this solution due to the following reasons
- You risk exposing your production database connection URL to version control. - You may accidentally use your production connection URL instead and in turn **override or delete your production database**.
We recommend setting up an automated CI/CD pipeline
The pipeline should handle deployment to staging and production environments, and use `migrate deploy` in a pipeline step. See the [deployment guides](/orm/prisma-client/deployment) for examples. ## Baselining a production database When you add Prisma Migrate to an **existing database**, you must [baseline](/orm/prisma-migrate/workflows/baselining) the production database. Baselining is performed **once**, and can be done from a local instance. ![Baselining production from local with Prisma ORM](/img/orm/baseline-production-from-local.png) --- # Caveats when deploying to AWS platforms URL: https://www.prisma.io/docs/orm/prisma-client/deployment/caveats-when-deploying-to-aws-platforms The following describes some caveats you might face when deploying to different AWS platforms. ## AWS RDS Proxy Prisma ORM is compatible with AWS RDS Proxy. However, there is no benefit in using it for connection pooling with Prisma ORM due to the way RDS Proxy pins connections: > "Your connections to the proxy can enter a state known as pinning. When a connection is pinned, each later transaction uses the same underlying database connection until the session ends. Other client connections also can't reuse that database connection until the session ends. The session ends when Prisma Client's connection is dropped." - [AWS RDS Proxy Docs](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-proxy-pinning.html) [Prepared statements (of any size) or query statements greater than 16 KB cause RDS Proxy to pin the session.](https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/rds-proxy-pinning.html) Because Prisma ORM uses prepared statements for all queries, you won't see any benefit when using RDS Proxy with Prisma ORM. ## AWS Elastic Beanstalk AWS Elastic Beanstalk is a PaaS-like deployment service that abstracts away infrastructure and allows you to deploy applications to AWS quickly. When deploying an app using Prisma Client to AWS Elastic Beanstalk, Prisma ORM generates the Prisma Client code into `node_modules`. This is typically done in a `postinstall` hook defined in a `package.json`. Because Beanstalk limits the ability to write to the filesystem in the `postinstall` hook, you need to create an [`.npmrc`](https://docs.npmjs.com/cli/v6/configuring-npm/npmrc/) file in the root of your project and add the following configuration: ```config file=.npmrc showLineNumbers unsafe-perm=true ``` Enabling `unsafe-perm` forces _npm_ to run as _root_, avoiding the filesystem access problem, thereby allowing the `prisma generate` command in the `postinstall` hook to generate your code. ### Error: @prisma/client did not initialize yet This error happens because AWS Elastic Beanstalk doesn't install `devDependencies`, which means that it doesn't pick up the Prisma CLI. To remedy this you can either: 1. Add the `prisma` CLI package to your `dependencies` instead of the `devDependencies`. (Making sure to run `npm install` afterward to update the `package-lock.json`). 2. Or install your `devDependencies` on AWS Elastic Beanstalk instances. To do this you must set the AWS Elastic Beanstalk `NPM_USE_PRODUCTION` environment property to false. ## AWS RDS Postgres When using Prisma ORM with AWS RDS Postgres, you may encounter connection issues or the following error during migration or runtime: ```bash Error: P1010: User was denied access on the database ``` ### Cause AWS RDS enforces SSL connections by default, and Prisma parses the database connection string with `rejectUnauthorized: true`, which requires a valid SSL certificate. If the certificate is not configured properly, Prisma cannot connect to the database. ### Solution To resolve this issue, update the `DATABASE_URL` environment variable to include the `sslmode=no-verify` option. This bypasses strict SSL certificate verification and allows Prisma to connect to the database. Update your `.env` file as follows: ```bash DATABASE_URL=postgresql://:@/?sslmode=no-verify&schema=public ``` ### Why This Works The `sslmode=no-verify` setting passes `rejectUnauthorized: false` to the SSL configuration via the [pg-connection-string](https://github.com/brianc/node-postgres/blob/95d7e620ef8b51743b4cbca05dd3c3ce858ecea7/packages/pg-connection-string/README.md?plain=1#L71) package. This disables strict certificate validation, allowing Prisma to establish a connection with the RDS database. ### Note While using `sslmode=no-verify` can be a quick fix, it bypasses SSL verification and might not meet security requirements for production environments. In such cases, ensure that a valid SSL certificate is properly configured. ## AWS Lambda upload limit AWS Lambda defines an **deployment package upload limit**, which includes: - All application code - Binaries like the [Prisma ORM query engine](/orm/more/under-the-hood/engines) The [deployment package (.zip) size limit for lambdas is 50MB](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-limits.html). When you prepare a deployment package, remove any files that the function does not require in production to keep the final .zip as small as possible. This includes some [Prisma ORM engine binaries](#deleting-prisma-orm-engines-that-are-not-required). ### Deleting Prisma ORM engines that are not required Prisma CLI downloads additional engine binaries that are **not required** in production. You can delete the following files and folders: 1. The entire `node_modules/@prisma/engines` folder (refer to the [sample bash script](https://github.com/prisma/ecosystem-tests/blob/13e74dc47eababa5d3c8f488b73fe7fc8bffead7/platforms-serverless/lambda/run.sh#L16) used by the Prisma end-to-end tests) 2. The **local engine file** for your development platform from the `node_modules/.prisma/client` folder. For example, your schema might define the following `binaryTargets` if you develop on Debian (`native`) but deploy to AWS Lambda (`rhel-openssl-3.0.x`): ```prisma binaryTargets = ["native", "rhel-openssl-3.0.x"] ``` In this scenario: - Keep `node_modules/.prisma/client/query-engine-rhel-openssl-3.0.x`, which is the engine file used by AWS Lambda - Delete `node_modules/.prisma/client/query-engine-debian-openssl-1.1.x`, which is only required locally > **Note**: When using Node.js 18 or earlier, the correct `binaryTarget` for AWS Lambda is `rhel-openssl-1.0.x`. `rhel-openssl-3.0.x` is the correct `binaryTarget` for Node.js versions greater than 18. --- # Deploy to a different OS URL: https://www.prisma.io/docs/orm/prisma-client/deployment/deploy-to-a-different-os Prisma Client depends on the [query engine](/orm/more/under-the-hood/engines) that is running as a binary on the same host as your application. The query engine is implemented in Rust and is used by Prisma Client in the form of executable binary files. The binary is downloaded when `prisma generate` is called. If you have developed your application on a Windows machine for example, and wish to upload to AWS Lambda, which is a Linux environment, you may encounter issues and be presented with some warnings in your terminal. To solve this, if you know ahead of time that you will be deploying to a different environment, you can use the [binary targets](/orm/prisma-schema/overview/generators#binary-targets) and specify which of the [supported operating systems](/orm/reference/prisma-schema-reference#binarytargets-options) binaries should be included. > **Note**: If your OS isn't supported you can include a [custom binary](/orm/more/under-the-hood/engines#using-custom-engine-libraries-or-binaries). --- # Deployment URL: https://www.prisma.io/docs/orm/prisma-client/deployment/index This section describes how to deploy Node.js applications that use Prisma Client and TypeScript to various platforms. ## In this section --- # Logging URL: https://www.prisma.io/docs/orm/prisma-client/observability-and-logging/logging Use the `PrismaClient` [`log`](/orm/reference/prisma-client-reference#log) parameter to configure [log levels](/orm/reference/prisma-client-reference#log-levels) , including warnings, errors, and information about the queries sent to the database. Prisma Client supports two types of logging: - Logging to [stdout](https://en.wikipedia.org/wiki/Standard_streams) (default) - Event-based logging (use [`$on()`](/orm/reference/prisma-client-reference#on) method to [subscribe to events](#event-based-logging)) You can also use the `DEBUG` environment variable to enable debugging output in Prisma Client. See [Debugging](/orm/prisma-client/debugging-and-troubleshooting/debugging) for more information. If you want a detailed insight into your Prisma Client's performance at the level of individual operations, see [Tracing](/orm/prisma-client/observability-and-logging/opentelemetry-tracing). ## Log to stdout The simplest way to print _all_ log levels to stdout is to pass in an array `LogLevel` objects: ```ts const prisma = new PrismaClient({ log: ['query', 'info', 'warn', 'error'], }) ``` This is the short form of passing in an array of `LogDefinition` objects where the value of `emit` is always `stdout`: ```ts const prisma = new PrismaClient({ log: [ { emit: 'stdout', level: 'query', }, { emit: 'stdout', level: 'error', }, { emit: 'stdout', level: 'info', }, { emit: 'stdout', level: 'warn', }, ], }) ``` ## Event-based logging To use event-based logging: 1. Set `emit` to `event` for a specific log level, such as query 2. Use the `$on()` method to subscribe to the event The following example subscribes to all `query` events and write the `duration` and `query` to console: ```ts highlight=4,5,22-26;normal const prisma = new PrismaClient({ log: [ { emit: 'event', level: 'query', }, { emit: 'stdout', level: 'error', }, { emit: 'stdout', level: 'info', }, { emit: 'stdout', level: 'warn', }, ], }) prisma.$on('query', (e) => { console.log('Query: ' + e.query) console.log('Params: ' + e.params) console.log('Duration: ' + e.duration + 'ms') }) ``` ```sql no-copy Query: SELECT "public"."User"."id", "public"."User"."email", "public"."User"."name" FROM "public"."User" WHERE 1=1 OFFSET $1 Params: [0] Duration: 3ms Query: SELECT "public"."Post"."id", "public"."Post"."title", "public"."Post"."authorId" FROM "public"."Post" WHERE "public"."Post"."authorId" IN ($1,$2,$3,$4) OFFSET $5 Params: [2, 7, 18, 29] Duration: 2ms ``` ```ts highlight=4,5,22-25;normal const prisma = new PrismaClient({ log: [ { emit: 'event', level: 'query', }, { emit: 'stdout', level: 'error', }, { emit: 'stdout', level: 'info', }, { emit: 'stdout', level: 'warn', }, ], }) prisma.$on('query', (e) => { console.log('Query: ' + e.query) }) ``` ```terminal no-copy Query: db.User.aggregate([ { $project: { _id: 1, email: 1, name: 1, }, }, ]) Query: db.Post.aggregate([ { $match: { userId: { $in: [ "622f0bbbdf635a42016ee325", ], }, }, }, { $project: { _id: 1, slug: 1, title: 1, body: 1, userId: 1, }, }, ]) ``` The exact [event (`e`) type and the properties available](/orm/reference/prisma-client-reference#event-types) depends on the log level. --- # Metrics URL: https://www.prisma.io/docs/orm/prisma-client/observability-and-logging/metrics Prisma Client metrics give you a detailed insight into how Prisma Client interacts with your database. You can use this insight to help diagnose performance issues with your application. If you want an even more detailed insight into your Prisma Client's performance, at the level of individual operations, see [Tracing](/orm/prisma-client/observability-and-logging/opentelemetry-tracing). ## About metrics You can export metrics in JSON or Prometheus formats and view them in a console log, or integrate them into an external metrics system, such as [StatsD](https://github.com/statsd/statsd) or [Prometheus](https://prometheus.io/). If you integrate them into an external metrics system, then you can view the metrics data over time. For example, you can use metrics to help diagnose how your application's number of idle and active connections changes. Prisma Client provides the following metrics: - Counters (always increase): - `prisma_client_queries_total`: The total number of Prisma Client queries executed. - `prisma_datasource_queries_total`: The total number of datasource queries executed (SQL queries in relational databases, and commands in MongoDB). - The value returned by `prisma_datasource_queries_total` can be greater than `prisma_client_queries_total`, because some Prisma Client operations create multiple queries. - `prisma_pool_connections_closed_total`: The total number of pool connections closed. - `prisma_pool_connections_opened_total`: The number of currently open pool connections. - Gauges (can increase or decrease): - `prisma_client_queries_active`: The number of currently active Prisma Client queries. - `prisma_client_queries_wait`: The number of Prisma Client queries currently waiting for a connection because all connections are in use. - `prisma_pool_connections_busy`: The number of currently busy pool connections. These pool connections are currently executing a datasource query. - `prisma_pool_connections_idle`: The number of pool connections that are not currently being used. These pool connections are waiting for the next datasource query to run. - `prisma_pool_connections_open`: The number of [pool connections](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool#default-connection-pool-size) open. - Histograms (metrics data divided into a collection of values; we call each container in the collection a "bucket"): - `prisma_client_queries_wait_histogram_ms`: The time waiting for a pool connection for all Prisma Client queries in ms. - `prisma_client_queries_duration_histogram_ms`: The execution time for all executed Prisma Client queries in ms. This includes the time taken to execute all database queries, and to carry out all database engine activities, such as joining data and transforming data to the correct format. - `prisma_datasource_queries_duration_histogram_ms`: The execution time for all executed Datasource queries in ms. You can [add global labels to your metrics data](#global-labels) to help you group and separate your metrics, for example by infrastructure region or server. ## Prerequisites To use Prisma Client metrics, you must do the following: 1. [Install the appropriate dependencies](#1-install-up-to-date-prisma-orm-dependencies). 1. [Enable the `metrics` feature flag in your Prisma schema file](#2-enable-the-feature-flag-in-the-prisma-schema-file). ### 1. Install up-to-date Prisma ORM dependencies Use version `3.15.0` or higher of the `prisma` and `@prisma/client` npm packages. ```terminal npm install prisma@latest --save-dev npm install @prisma/client@latest --save ``` ### 2. Enable the feature flag in the Prisma schema file In the `generator` block of your `schema.prisma` file, enable the `metrics` feature flag: ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["metrics"] } ``` ## Retrieve metrics in JSON format When you retrieve metrics in JSON format, you can use them in the format they are returned, or [send them to StatSD](#use-prisma-client-metrics-with-statsd) to visualize how they change over time. To retrieve metrics in JSON format, add the following lines to your application code: ```ts const metrics = await prisma.$metrics.json() console.log(metrics) ``` This returns metrics as follows: ```json { "counters": [ { "key": "prisma_client_queries_total", "labels": {}, "value": 0, "description": "Total number of Prisma Client queries executed" }, { "key": "prisma_datasource_queries_total", "labels": {}, "value": 0, "description": "Total number of Datasource Queries executed" }, { "key": "prisma_pool_connections_closed_total", "labels": {}, "value": 0, "description": "Total number of Pool Connections closed" }, { "key": "prisma_pool_connections_opened_total", "labels": {}, "value": 1, "description": "Total number of Pool Connections opened" } ... ], "gauges": [ ... ], "histograms": [ ... ] } ```
Expand to view the full output ```json no-copy { "counters": [ { "key": "prisma_client_queries_total", "labels": {}, "value": 2, "description": "Total number of Prisma Client queries executed" }, { "key": "prisma_datasource_queries_total", "labels": {}, "value": 5, "description": "Total number of Datasource Queries executed" }, { "key": "prisma_pool_connections_open", "labels": {}, "value": 1, "description": "Number of currently open Pool Connections" } ], "gauges": [ { "key": "prisma_client_queries_active", "labels": {}, "value": 0, "description": "Number of currently active Prisma Client queries" }, { "key": "prisma_client_queries_wait", "labels": {}, "value": 0, "description": "Number of Prisma Client queries currently waiting for a connection" }, { "key": "prisma_pool_connections_busy", "labels": {}, "value": 0, "description": "Number of currently busy Pool Connections (executing a datasource query)" }, { "key": "prisma_pool_connections_idle", "labels": {}, "value": 21, "description": "Number of currently unused Pool Connections (waiting for the next datasource query to run)" }, { "key": "prisma_pool_connections_open", "labels": {}, "value": 1, "description": "Number of currently open Pool Connections" } ], "histograms": [ { "key": "prisma_client_queries_duration_histogram_ms", "labels": {}, "value": { "buckets": [ [0, 0], [1, 0], [5, 0], [10, 1], [50, 1], [100, 0], [500, 0], [1000, 0], [5000, 0], [50000, 0] ], "sum": 47.430541000000005, "count": 2 }, "description": "Histogram of the duration of all executed Prisma Client queries in ms" }, { "key": "prisma_client_queries_wait_histogram_ms", "labels": {}, "value": { "buckets": [ [0, 0], [1, 3], [5, 0], [10, 0], [50, 0], [100, 0], [500, 0], [1000, 0], [5000, 0], [50000, 0] ], "sum": 0.0015830000000000002, "count": 3 }, "description": "Histogram of the wait time of all Prisma Client Queries in ms" }, { "key": "prisma_datasource_queries_duration_histogram_ms", "labels": {}, "value": { "buckets": [ [0, 0], [1, 0], [5, 2], [10, 2], [50, 1], [100, 0], [500, 0], [1000, 0], [5000, 0], [50000, 0] ], "sum": 47.134498, "count": 5 }, "description": "Histogram of the duration of all executed Datasource Queries in ms" } ] } ```
### Histograms in JSON data Each histogram "bucket" has two values. The first one is the upper bound of the bucket, and the second one is the count (the number of data values that fall into that bucket). In the following example, there are two instances of values between 11 and 20, and five instances of values between 21 and 30: ```json ... [20, 2], [30, 5], ... ``` ### Use Prisma Client metrics with StatsD You can send JSON-formatted metrics to [StatsD](https://github.com/statsd/statsd) to visualize your metrics data over time. Note: You must provide counter metrics to StatsD as a series of values that are incremented or decremented from a previous retrieval of the metrics. However, Prisma Client's counter metrics return absolute values. Therefore, you must convert your counter metrics to a series of incremented and decremented values and send them to StatsD as gauge data. In the code example below, we convert counter metrics into incremented and decremented gauge data in `diffHistograms`. In the following example, we send metrics to StatsD every 10 seconds. This timing aligns with the default 10s flush rate of StatsD. ```ts import StatsD from 'hot-shots' let statsd = new StatsD({ port: 8125, }) const diffMetrics = (metrics: Metric[]) => { return metrics.map((metric) => { let prev = 0; const diffBuckets = metric.value.buckets.map( (values) => { const [bucket, value] = values const diff = value - prev prev = value return [bucket, diff] } ) metric.value.buckets = diffBuckets return metric }) } let previousHistograms: Metric[] = [] const statsdSender = async () => { const metrics = await prisma.$metrics.json() metrics.counters.forEach((counter: any) => { statsd.gauge('prisma.' + counter.key, counter.value, (...res) => {}) }); metrics.gauges.forEach((counter: any) => { statsd.gauge('prisma.' + counter.key, counter.value, (...res) => {}) }) if (!previousHistograms.length) { previousHistograms = diffMetrics(metrics.histograms) return } const diffHistograms = diffMetrics(metrics.histograms); diffHistograms.forEach((diffHistogram, histogramIndex) => { diffHistogram.value.buckets.forEach((values, bucketIndex) => { const [bucket, count] = values const [_, prev] = previousHistograms[histogramIndex].value.buckets[bucketIndex] const change = count - prev for (let sendTimes = 0; sendTimes < change; sendTimes++) { statsd.timing('prisma.' + diffHistograms.key, bucket) } }) }) previousHistograms = diffHistograms } setInterval(async () => await statsdSender(), 10000) ``` ## Retrieve metrics in Prometheus format When you retrieve Prisma Client metrics in Prometheus format, you can use them in the format they are returned, or [send them to the Prometheus metrics system](#use-prisma-client-metrics-with-the-prometheus-metrics-system) to visualize how they change over time. To retrieve metrics in Prometheus format, add the following lines to your application code: ```ts const metrics = await prisma.$metrics.prometheus() console.log(metrics) ``` This returns metrics as follows: ```c # HELP prisma_client_queries_total Total number of Prisma Client queries executed # TYPE prisma_client_queries_total counter prisma_client_queries_total 14 ... # HELP prisma_pool_connections_busy The number of active connections in use. # TYPE prisma_pool_connections_busy gauge prisma_pool_connections_busy 0 ... # HELP prisma_client_queries_wait_histogram_ms The wait time for a worker to get a connection. # TYPE prisma_client_queries_wait_histogram_ms histogram prisma_client_queries_wait_histogram_ms_bucket{le="0"} 0 prisma_client_queries_wait_histogram_ms_bucket{le="1"} 3 ```
Expand to view the full output ```c # HELP query_total_operations # TYPE query_total_operations counter query_total_operations 2 # HELP prisma_datasource_queries_total # TYPE prisma_datasource_queries_total counter prisma_datasource_queries_total 28 # HELP prisma_pool_connections_closed_total Total number of Pool Connections closed # TYPE prisma_pool_connections_closed_total counter prisma_pool_connections_closed_total 0 # HELP prisma_pool_connections_opened_total Total number of Pool Connections opened # TYPE prisma_pool_connections_opened_total counter prisma_pool_connections_opened_total 0 # HELP prisma_client_queries_active Number of currently active Prisma Client queries # TYPE prisma_client_queries_active gauge prisma_client_queries_active 0 # HELP prisma_client_queries_wait Number of queries currently waiting for a connection # TYPE prisma_client_queries_wait gauge prisma_client_queries_wait 0 # HELP prisma_pool_connections_busy Number of currently busy Pool Connections (executing a datasource query) # TYPE prisma_pool_connections_busy gauge prisma_pool_connections_busy 0 # HELP prisma_pool_connections_idle Number of currently unused Pool Connections (waiting for the next pool query to run) # TYPE prisma_pool_connections_idle gauge prisma_pool_connections_idle 21 # HELP prisma_pool_connections_open Number of currently open Pool Connections # TYPE prisma_pool_connections_open gauge prisma_pool_connections_open 1 # HELP prisma_pool_connections_open Number of currently open Pool Connections (able to execute a datasource query) # TYPE prisma_pool_connections_open gauge prisma_pool_connections_open 0 # HELP prisma_client_queries_wait_histogram_ms The wait time for a worker to get a connection. # TYPE prisma_client_queries_wait_histogram_ms histogram prisma_client_queries_wait_histogram_ms_bucket{le="0"} 0 prisma_client_queries_wait_histogram_ms_bucket{le="1"} 3 prisma_client_queries_wait_histogram_ms_bucket{le="5"} 3 prisma_client_queries_wait_histogram_ms_bucket{le="10"} 3 prisma_client_queries_wait_histogram_ms_bucket{le="50"} 3 prisma_client_queries_wait_histogram_ms_bucket{le="100"} 3 prisma_client_queries_wait_histogram_ms_bucket{le="500"} 3 prisma_client_queries_wait_histogram_ms_bucket{le="1000"} 3 prisma_client_queries_wait_histogram_ms_bucket{le="5000"} 3 prisma_client_queries_wait_histogram_ms_bucket{le="50000"} 3 prisma_client_queries_wait_histogram_ms_bucket{le="+Inf"} 3 prisma_client_queries_wait_histogram_ms_sum 0.023208 prisma_client_queries_wait_histogram_ms_count 3 # HELP prisma_client_queries_duration_histogram_ms Histogram of the duration of all executed Prisma Client queries in ms # TYPE prisma_client_queries_duration_histogram_ms histogram prisma_client_queries_duration_histogram_ms_bucket{le="0"} 0 prisma_client_queries_duration_histogram_ms_bucket{le="1"} 1 prisma_client_queries_duration_histogram_ms_bucket{le="5"} 2 prisma_client_queries_duration_histogram_ms_bucket{le="10"} 2 prisma_client_queries_duration_histogram_ms_bucket{le="50"} 2 prisma_client_queries_duration_histogram_ms_bucket{le="100"} 2 prisma_client_queries_duration_histogram_ms_bucket{le="500"} 2 prisma_client_queries_duration_histogram_ms_bucket{le="1000"} 2 prisma_client_queries_duration_histogram_ms_bucket{le="5000"} 2 prisma_client_queries_duration_histogram_ms_bucket{le="50000"} 2 prisma_client_queries_duration_histogram_ms_bucket{le="+Inf"} 2 prisma_client_queries_duration_histogram_ms_sum 3.197624 prisma_client_queries_duration_histogram_ms_count 2 # HELP prisma_datasource_queries_duration_histogram_ms Histogram of the duration of all executed Datasource Queries in ms # TYPE prisma_datasource_queries_duration_histogram_ms histogram prisma_datasource_queries_duration_histogram_ms_bucket{le="0"} 0 prisma_datasource_queries_duration_histogram_ms_bucket{le="1"} 5 prisma_datasource_queries_duration_histogram_ms_bucket{le="5"} 5 prisma_datasource_queries_duration_histogram_ms_bucket{le="10"} 5 prisma_datasource_queries_duration_histogram_ms_bucket{le="50"} 5 prisma_datasource_queries_duration_histogram_ms_bucket{le="100"} 5 prisma_datasource_queries_duration_histogram_ms_bucket{le="500"} 5 prisma_datasource_queries_duration_histogram_ms_bucket{le="1000"} 5 prisma_datasource_queries_duration_histogram_ms_bucket{le="5000"} 5 prisma_datasource_queries_duration_histogram_ms_bucket{le="50000"} 5 prisma_datasource_queries_duration_histogram_ms_bucket{le="+Inf"} 5 prisma_datasource_queries_duration_histogram_ms_sum 1.8407059999999997 prisma_datasource_queries_duration_histogram_ms_count 5 ```
Metrics of type `histogram` expose three different class of values in the Prometheus format: 1. Multiple cumulative counters for observation buckets. These counters are suffixed with `_bucket{le=""}`. For example, `prisma_datasource_queries_duration_histogram_ms` has a counter exposed as `prisma_datasource_queries_duration_histogram_ms_bucket{le="1"}` When an observed value is less than or equal to the upper inclusive bound of a bucket, then Prisma Client metrics increments that bucket by 1. Suppose that you have buckets with the upper inclusive bounds 0, 1, 5, 10, and 50 respectively. If the observed value is 5 then Prisma Client metrics increments the third bucket onwards, because the value is greater than 0 and greater than 1, but less than or equal to 5, 10, and 50. 2. A single **total sum** for all observed values. This counter is suffixed with `_sum`. For example the total sum of `prisma_datasource_queries_duration_histogram_ms` is exposed as `prisma_datasource_queries_duration_histogram_ms_sum`. 3. The **count** of the number of events that have been observed. This counter is suffixed with `_count`. For example the total count of `prisma_datasource_queries_duration_histogram_ms` events is exposed as `prisma_datasource_queries_duration_histogram_ms_count`. For more information, read the Prometheus documentation on [metric types](https://prometheus.io/docs/concepts/metric_types/#histogram). ### Use Prisma Client metrics with the Prometheus metrics system In the majority of cases, Prometheus must scrape an endpoint to retrieve metrics. The following example shows how to send data with `Express.js`: ```js import { PrismaClient } from '@prisma/client' import express, { Request, Response } from 'express' const app = express() const port = 4000 const prisma = new PrismaClient() app.get('/metrics', async (_req, res: Response) => { const metrics = await prisma.$metrics.prometheus() res.end(metrics) }) app.listen(port, () => { console.log(`Example app listening on port ${port}`) }) ``` The following example shows how to combine Prisma Client metrics with other Prometheus client libraries that are also served with a REST API endpoint in conjunction with `Express.js`: ```js import { PrismaClient } from '@prisma/client' import express, { Request, Response } from 'express' import prom from 'prom-client' const app = express() const port = 4000 const prisma = new PrismaClient() const register = new prom.Registry() prom.collectDefaultMetrics({ register }) app.get('/metrics', async (_req, res: Response) => { const prismaMetrics = await prisma.$metrics.prometheus() const appMetrics = await register.metrics() res.end(prismaMetrics + appMetrics) }) app.listen(port, () => { console.log(`Example app listening on port ${port}`) }) ``` ## Global labels You can add global labels to your metrics to help you group and separate your metrics. Each instance of Prisma Client adds these labels to the metrics that it generates. For example, you can group your metrics by infrastructure region, or by server, with a label like `{ server: us_server1', 'app_version': 'one' }`. Global labels work with JSON and Prometheus-formatted metrics. For example, to add global labels to JSON-format metrics, add the following code to your application: ```ts const metrics = prisma.$metrics.json({ globalLabels: { server: 'us_server1', app_version: 'one' }, }) console.log(metrics) ``` This returns information in the following format: ```json highlight=5,11;add { "counters": [ { "key": "query_total_operations", //add-next-line "labels": { "server": "us_server1", "app_version": "one" }, "value": 0, "description": "The total number of operations executed" }, { "key": "prisma_datasource_queries_total", //add-next-line "labels": { "server": "us_server1", "app_version": "one" }, "value": 0, "description": "The total number of queries executed" }, ... ], "gauges": [ ... ], "histograms": [ ... ] } ``` --- # OpenTelemetry tracing URL: https://www.prisma.io/docs/orm/prisma-client/observability-and-logging/opentelemetry-tracing Tracing provides a detailed log of the activity that Prisma Client carries out, at an operation level, including the time taken to execute each query. It helps you analyze your application's performance and identify bottlenecks. Tracing is fully compliant with [OpenTelemetry](https://opentelemetry.io/), so you can use it as part of your end-to-end application tracing system. :::info Tracing gives you a highly detailed, operation-level insight into your Prisma ORM project. If you want aggregated numerical reporting, such as query counts, connection counts, and total query execution times, see [Metrics](/orm/prisma-client/observability-and-logging/metrics). ::: ## About tracing When you enable tracing, Prisma Client outputs the following: - One trace for each operation (e.g. findMany) that Prisma Client makes. - In each trace, one or more [spans](https://opentelemetry.io/docs/specs/otel/trace/api/#span). Each span represents the length of time that one stage of the operation takes, such as serialization, or a database query. Spans are represented in a tree structure, where child spans indicate that execution is happening within a larger parent span. The number and type of spans in a trace depends on the type of operation the trace covers, but an example is as follows: ![image](./trace-diagram.png) You can [send tracing output to the console](#send-tracing-output-to-the-console), or analyze it in any OpenTelemetry-compatible tracing system, such as [Jaeger](https://www.jaegertracing.io/), [Honeycomb](https://www.honeycomb.io/distributed-tracing) and [Datadog](https://www.datadoghq.com/). On this page, we give an example of how to send tracing output to Jaeger, which you can [run locally](#visualize-traces-with-jaeger). ## Trace output For each trace, Prisma Client outputs a series of spans. The number and type of these spans depends on the Prisma Client operation. A typical Prisma trace has the following spans: - `prisma:client:operation`: Represents the entire Prisma Client operation, from Prisma Client to the database and back. It contains details such as the model and method called by Prisma Client. Depending on the Prisma operation, it contains one or more of the following spans: - `prisma:client:connect`: Represents how long it takes for Prisma Client to connect to the database. - `prisma:client:serialize`: Represents how long it takes to validate and transform a Prisma Client operation into a query for the [query engine](/orm/more/under-the-hood/engines). - `prisma:engine:query`: Represents how long a query takes in the query engine. - `prisma:engine:connection`: Represents how long it takes for Prisma Client to get a database connection. - `prisma:engine:db_query`: Represents the database query that was executed against the database. It includes the query in the tags, and how long the query took to run. - `prisma:engine:serialize`: Represents how long it takes to transform a raw response from the database into a typed result. - `prisma:engine:response_json_serialization`: Represents how long it takes to serialize the database query result into a JSON response to the Prisma Client. For example, given the following Prisma Client code: ```ts prisma.user.findMany({ where: { email: email, }, include: { posts: true, }, }) ``` The trace is structured as follows: - `prisma:client:operation` - `prisma:client:serialize` - `prisma:engine:query` - `prisma:engine:connection` - `prisma:engine:db_query`: details of the first SQL query or command... - `prisma:engine:db_query`: ...details of the next SQL query or command... - `prisma:engine:serialize` - `prisma:engine:response_json_serialization` ## Considerations and prerequisites If your application sends a large number of spans to a [collector](https://opentelemetry.io/docs/collector/), this can have a significant performance impact. For information on how to minimize this impact, see [Reducing performance impact](#reduce-performance-impact). To use tracing, you must do the following: 1. [Install the appropriate dependencies](#step-1-install-up-to-date-prisma-orm-dependencies). 1. [Install OpenTelemetry packages](#step-2-install-opentelemetry-packages). 1. [Register tracing in your application](#step-3-register-tracing-in-your-application). ## Get started with tracing in Prisma ORM This section explains how to install and register tracing in your application. ### Step 1. Install up-to-date Prisma ORM dependencies Use version `6.1.0` or later of the `prisma`, `@prisma/client`, and `@prisma/instrumentation` npm packages. You will also need to install the `@opentelemetry/api` package as it's a peer dependency. ```terminal npm install prisma@latest --save-dev npm install @prisma/client@latest --save npm install @prisma/instrumentation@latest --save npm install @opentelemetry/api@latest --save ```
Tracing on previous versions of Prisma ORM Tracing was added in version `4.2.0` of Prisma ORM as a Preview feature. For versions of Prisma ORM between `4.2.0` and `6.1.0`, you need to enable the `tracing` Preview feature in your Prisma schema file. ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["tracing"] } ```
### Step 2: Install OpenTelemetry packages Now install the appropriate OpenTelemetry packages, as follows: ```console npm install @opentelemetry/semantic-conventions @opentelemetry/exporter-trace-otlp-http @opentelemetry/sdk-trace-base @opentelemetry/sdk-trace-node @opentelemetry/resources ``` ### Step 3: Register tracing in your application The following code provides two examples of configuring OpenTelemetry tracing in Prisma: 1. Using `@opentelemetry/sdk-trace-node` (existing example), which gives fine-grained control over tracing setup. 2. Using `@opentelemetry/sdk-node`, which offers a simpler configuration and aligns with OpenTelemetry's JavaScript getting started guide. --- #### Option 1: Using `@opentelemetry/sdk-trace-node` This setup gives you fine-grained control over instrumentation and tracing. You need to customize this configuration for your specific application. This approach is concise and easier for users who need a quick setup for sending traces to OTLP-compatible backends, such as Honeycomb, Jaeger, or Datadog. ```ts // Imports import { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions' import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http' import { SimpleSpanProcessor } from '@opentelemetry/sdk-trace-base' import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node' import { PrismaInstrumentation, registerInstrumentations } from '@prisma/instrumentation' import { Resource } from '@opentelemetry/resources' // Configure the trace provider const provider = new NodeTracerProvider({ resource: new Resource({ [SEMRESATTRS_SERVICE_NAME]: 'example application', // Replace with your service name [SEMRESATTRS_SERVICE_VERSION]: '0.0.1', // Replace with your service version }), }) // Configure how spans are processed and exported. In this case, we're sending spans // as we receive them to an OTLP-compatible collector (e.g., Jaeger). provider.addSpanProcessor(new SimpleSpanProcessor(new OTLPTraceExporter())) // Register your auto-instrumentors registerInstrumentations({ tracerProvider: provider, instrumentations: [new PrismaInstrumentation()], }) // Register the provider globally provider.register() ``` This approach provides maximum flexibility but may involve additional configuration steps. #### Option 2: Using `@opentelemetry/sdk-node` For many users, especially beginners, the `NodeSDK` class simplifies OpenTelemetry setup by bundling common defaults into a single, unified configuration. ```ts // Imports import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-proto' import { NodeSDK } from '@opentelemetry/sdk-node' import { PrismaInstrumentation } from '@prisma/instrumentation' // Configure the OTLP trace exporter const traceExporter = new OTLPTraceExporter({ url: 'https://api.honeycomb.io/v1/traces', // Replace with your collector's endpoint headers: { 'x-honeycomb-team': 'HONEYCOMB_API_KEY', // Replace with your Honeycomb API key or collector auth header }, }) // Initialize the NodeSDK const sdk = new NodeSDK({ serviceName: 'my-service-name', // Replace with your service name traceExporter, instrumentations: [ new PrismaInstrumentation({ middleware: true, // Enable middleware tracing if needed }), ], }) // Start the SDK sdk.start() // Handle graceful shutdown process.on('SIGTERM', async () => { try { await sdk.shutdown() console.log('Tracing shut down successfully') } catch (err) { console.error('Error shutting down tracing', err) } finally { process.exit(0) } }) ``` Choose the `NodeSDK` approach if: - You are starting with OpenTelemetry and want a simplified setup. - You need to quickly integrate tracing with minimal boilerplate. - You are using an OTLP-compatible tracing backend like Honeycomb, Jaeger, or Datadog. Choose the `NodeTracerProvider` approach if: - You need detailed control over how spans are created, processed, and exported. - You are using custom span processors or exporters. - Your application requires specific instrumentation or sampling strategies. OpenTelemetry is highly configurable. You can customize the resource attributes, what components gets instrumented, how spans are processed, and where spans are sent. You can find a complete example that includes metrics in [this sample application](https://github.com/garrensmith/prisma-metrics-sample). ## Tracing how-tos ### Visualize traces with Jaeger [Jaeger](https://www.jaegertracing.io/) is a free and open source OpenTelemetry collector and dashboard that you can use to visualize your traces. The following screenshot shows an example trace visualization: ![Jaeger UI](./jaeger.png) To run Jaeger locally, use the following [Docker](https://www.docker.com/) command: ```console docker run --rm --name jaeger -d -e COLLECTOR_OTLP_ENABLED=true -p 16686:16686 -p 4318:4318 jaegertracing/all-in-one:latest ``` You'll now find the tracing dashboard available at `http://localhost:16686/`. When you use your application with tracing enabled, you'll start to see traces in this dashboard. ### Send tracing output to the console The following example sends output tracing to the console with `ConsoleSpanExporter` from `@opentelemetry/sdk-trace-base`. ```ts // Imports import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions' import { BasicTracerProvider, ConsoleSpanExporter, SimpleSpanProcessor, } from '@opentelemetry/sdk-trace-base' import { AsyncHooksContextManager } from '@opentelemetry/context-async-hooks' import * as api from '@opentelemetry/api' import { PrismaInstrumentation, registerInstrumentations } from '@prisma/instrumentation' import { Resource } from '@opentelemetry/resources' // Export the tracing export function otelSetup() { const contextManager = new AsyncHooksContextManager().enable() api.context.setGlobalContextManager(contextManager) //Configure the console exporter const consoleExporter = new ConsoleSpanExporter() // Configure the trace provider const provider = new BasicTracerProvider({ resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: 'test-tracing-service', [SemanticResourceAttributes.SERVICE_VERSION]: '1.0.0', }), }) // Configure how spans are processed and exported. In this case we're sending spans // as we receive them to the console provider.addSpanProcessor(new SimpleSpanProcessor(consoleExporter)) // Register your auto-instrumentors registerInstrumentations({ tracerProvider: provider, instrumentations: [new PrismaInstrumentation()], }) // Register the provider provider.register() } ``` ### Trace Prisma Client middleware By default, tracing does not output spans for [Prisma Client middleware](/orm/prisma-client/client-extensions/middleware). To include your middleware in your traces, set `middleware` to `true` in your `registerInstrumentations` statement, as follows: ```ts registerInstrumentations({ instrumentations: [new PrismaInstrumentation({ middleware: true })], }) ``` This will add the following span type to your traces: - `prisma:client:middleware`: Represents how long the operation spent in your [middleware](/orm/prisma-client/client-extensions/middleware). ### Trace interactive transactions When you perform an interactive transaction, you'll see the following spans in addition to the [standard spans](#trace-output): - `prisma:client:transaction`: A [root span](https://opentelemetry.io/docs/concepts/observability-primer/#distributed-traces) that wraps the `prisma` span. - `prisma:engine:itx_runner`: Represents how long an interactive transaction takes in the [query engine](/orm/more/under-the-hood/engines). - `prisma:engine:itx_query_builder`: Represents the time it takes to build an interactive transaction. As an example, take the following Prisma schema: ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) email String @unique } model Audit { id Int @id table String action String } ``` Given the following interactive transaction: ```ts await prisma.$transaction(async (tx) => { const user = await tx.user.create({ data: { email: email, }, }) await tx.audit.create({ data: { table: 'user', action: 'create', id: user.id, }, }) return user }) ``` The trace is structured as follows: - `prisma:client:transaction` - `prisma:client:connect` - `prisma:engine:itx_runner` - `prisma:engine:connection` - `prisma:engine:db_query` - `prisma:engine:itx_query_builder` - `prisma:engine:db_query` - `prisma:engine:db_query` - `prisma:engine:serialize` - `prisma:engine:itx_query_builder` - `prisma:engine:db_query` - `prisma:engine:db_query` - `prisma:engine:serialize` - `prisma:client:operation` - `prisma:client:serialize` - `prisma:client:operation` - `prisma:client:serialize` ### Add more instrumentation A nice benefit of OpenTelemetry is the ability to add more instrumentation with only minimal changes to your application code. For example, to add HTTP and [ExpressJS](https://expressjs.com/) tracing, add the following instrumentations to your OpenTelemetry configuration. These instrumentations add spans for the full request-response lifecycle. These spans show you how long your HTTP requests take. ```js // Imports import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express' import { HttpInstrumentation } from '@opentelemetry/instrumentation-http' // Register your auto-instrumentors registerInstrumentations({ tracerProvider: provider, instrumentations: [ new HttpInstrumentation(), new ExpressInstrumentation(), new PrismaInstrumentation(), ], }) ``` For a full list of available instrumentation, take a look at the [OpenTelemetry Registry](https://opentelemetry.io/ecosystem/registry/?language=js&component=instrumentation). ### Customize resource attributes You can adjust how your application's traces are grouped by changing the resource attributes to be more specific to your application: ```js const provider = new NodeTracerProvider({ resource: new Resource({ [SemanticResourceAttributes.SERVICE_NAME]: 'weblog', [SemanticResourceAttributes.SERVICE_VERSION]: '1.0.0', }), }) ``` There is an ongoing effort to standardize common resource attributes. Whenever possible, it's a good idea to follow the [standard attribute names](https://github.com/open-telemetry/semantic-conventions/blob/main/docs/general/trace.md). ### Reduce performance impact If your application sends a large number of spans to a collector, this can have a significant performance impact. You can use the following approaches to reduce this impact: - [Use the BatchSpanProcessor](#send-traces-in-batches-using-the-batchspanprocessor) - [Send fewer spans to the collector](#send-fewer-spans-to-the-collector-with-sampling) #### Send traces in batches using the `BatchSpanProcessor` In a production environment, you can use OpenTelemetry's `BatchSpanProcessor` to send the spans to a collector in batches rather than one at a time. However, during development and testing, you might not want to send spans in batches. In this situation, you might prefer to use the `SimpleSpanProcessor`. You can configure your tracing configuration to use the appropriate span processor, depending on the environment, as follows: ```ts import { SimpleSpanProcessor, BatchSpanProcessor, } from '@opentelemetry/sdk-trace-base' if (process.env.NODE_ENV === 'production') { provider.addSpanProcessor(new BatchSpanProcessor(otlpTraceExporter)) } else { provider.addSpanProcessor(new SimpleSpanProcessor(otlpTraceExporter)) } ``` #### Send fewer spans to the collector with sampling Another way to reduce the performance impact is to [use probability sampling](https://opentelemetry.io/docs/specs/otel/trace/tracestate-probability-sampling/) to send fewer spans to the collector. This reduces the collection cost of tracing but still gives a good representation of what is happening in your application. An example implementation looks like this: ```ts highlight=3,7;add import { SemanticResourceAttributes } from '@opentelemetry/semantic-conventions' import { NodeTracerProvider } from '@opentelemetry/sdk-trace-node' //add-next-line import { TraceIdRatioBasedSampler } from '@opentelemetry/core' import { Resource } from '@opentelemetry/resources' const provider = new NodeTracerProvider({ //add-next-line sampler: new TraceIdRatioBasedSampler(0.1), resource: new Resource({ // we can define some metadata about the trace resource [SemanticResourceAttributes.SERVICE_NAME]: 'test-tracing-service', [SemanticResourceAttributes.SERVICE_VERSION]: '1.0.0', }), }) ``` ## Troubleshoot tracing ### My traces aren't showing up The order in which you set up tracing matters. In your application, ensure that you register tracing and instrumentation before you import any instrumented dependencies. For example: ```ts import { registerTracing } from './tracing' registerTracing({ name: 'tracing-example', version: '0.0.1', }) // You must import any dependencies after you register tracing. import { PrismaClient } from '@prisma/client' import async from 'express-async-handler' import express from 'express' ``` --- # Observability & logging URL: https://www.prisma.io/docs/orm/prisma-client/observability-and-logging/index ## In this section :::tip Get query insights and analytics with Prisma Optimize [Prisma Optimize](/optimize) helps you generate insights and provides recommendations that can help you make your database queries faster: Optimize aims to help developers of all skill levels write efficient database queries, reducing database load and making applications more responsive. ::: --- # Debugging URL: https://www.prisma.io/docs/orm/prisma-client/debugging-and-troubleshooting/debugging You can enable debugging output in Prisma Client and Prisma CLI via the [`DEBUG`](/orm/reference/environment-variables-reference#debug) environment variable. It accepts two namespaces to print debugging output: - `prisma:engine`: Prints relevant debug messages happening in a Prisma ORM [engine](https://github.com/prisma/prisma-engines/) - `prisma:client`: Prints relevant debug messages happening in the Prisma Client runtime - `prisma*`: Prints all debug messages from Prisma Client or CLI - `*`: Prints all debug messages Prisma Client can be configured to log warnings, errors and information related to queries sent to the database. See [Configuring logging](/orm/prisma-client/observability-and-logging/logging) for more information. ## Setting the `DEBUG` environment variable Here are examples for setting these debugging options in bash: ```terminal # enable only `prisma:engine`-level debugging output export DEBUG="prisma:engine" # enable only `prisma:client`-level debugging output export DEBUG="prisma:client" # enable both `prisma-client`- and `engine`-level debugging output export DEBUG="prisma:client,prisma:engine" ``` To enable all `prisma` debugging options, set `DEBUG` to `prisma*`: ```terminal export DEBUG="prisma*" ``` On Windows, use `set` instead of `export`: ```terminal set DEBUG="prisma*" ``` To enable _all_ debugging options, set `DEBUG` to `*`: ```terminal export DEBUG="*" ``` --- # Handling exceptions and errors URL: https://www.prisma.io/docs/orm/prisma-client/debugging-and-troubleshooting/handling-exceptions-and-errors In order to handle different types of errors you can use `instanceof` to check what the error is and handle it accordingly. The following example tries to create a user with an already existing email record. This will throw an error because the `email` field has the `@unique` attribute applied to it. ```prisma file=schema.prisma showLineNumbers model User { id Int @id @default(autoincrement()) email String @unique name String? } ``` Use the `Prisma` namespace to access the error type. The [error code](/orm/reference/error-reference#error-codes) can then be checked and a message can be printed. ```ts import { PrismaClient, Prisma } from '@prisma/client' const client = new PrismaClient() try { await client.user.create({ data: { email: 'alreadyexisting@mail.com' } }) } catch (e) { if (e instanceof Prisma.PrismaClientKnownRequestError) { // The .code property can be accessed in a type-safe manner if (e.code === 'P2002') { console.log( 'There is a unique constraint violation, a new user cannot be created with this email' ) } } throw e } ``` See [Errors reference](/orm/reference/error-reference) for a detailed breakdown of the different error types and their codes. --- # Debugging & troubleshooting URL: https://www.prisma.io/docs/orm/prisma-client/debugging-and-troubleshooting/index :::tip Get query insights and analytics with Prisma Optimize [Prisma Optimize](/optimize) helps you generate insights and provides recommendations that can help you make your database queries faster: Optimize aims to help developers of all skill levels write efficient database queries, reducing database load and making applications more responsive. ::: ## In this section --- # Prisma Client URL: https://www.prisma.io/docs/orm/prisma-client/index ## In this section --- # Getting started with Prisma Migrate URL: https://www.prisma.io/docs/orm/prisma-migrate/getting-started This page explains how to get started with migrating your schema in a development environment using Prisma Migrate. ## Get started with Prisma Migrate from scratch To get started with Prisma Migrate in a development environment: 1. Create a Prisma schema: ```prisma file=schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) name String posts Post[] } model Post { id Int @id @default(autoincrement()) title String published Boolean @default(true) authorId Int author User @relation(fields: [authorId], references: [id]) } ``` :::tip You can use [native type mapping attributes](/orm/prisma-migrate/workflows/native-database-types) in your schema to decide which exact database type to create (for example, `String` can map to `varchar(100)` or `text`). ::: 1. Create the first migration: ```terminal prisma migrate dev --name init ``` ```sql no-copy -- CreateTable CREATE TABLE "User" ( "id" SERIAL, "name" TEXT NOT NULL, PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "Post" ( "id" SERIAL, "title" TEXT NOT NULL, "published" BOOLEAN NOT NULL DEFAULT true, "authorId" INTEGER NOT NULL, PRIMARY KEY ("id") ); -- AddForeignKey ALTER TABLE "Post" ADD FOREIGN KEY("authorId")REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; ``` > **Note**: If you do not provide a `--name`, Prisma CLI will prompt you for a name. Your Prisma schema is now in sync with your database schema and you have initialized a migration history: ``` migrations/ └─ 20210313140442_init/ └─ migration.sql ``` 1. Add additional fields to your schema: ```prisma highlight=3;add model User { id Int @id @default(autoincrement()) //add-next-line jobTitle String name String posts Post[] } ``` 1. Create the second migration: ```terminal prisma migrate dev --name added_job_title ``` ```sql no-copy -- AlterTable ALTER TABLE "User" ADD COLUMN "jobTitle" TEXT NOT NULL; ``` Your Prisma schema is once again in sync with your database schema, and your migration history contains two migrations: ``` migrations/ └─ 20210313140442_init/ └─ migration.sql └─ 20210313140442_added_job_title/ └─ migration.sql ``` You now have a migration history that you can [source control](/orm/prisma-migrate/understanding-prisma-migrate/migration-histories#committing-the-migration-history-to-source-control) and use to [deploy changes to test environments and production](/orm/prisma-migrate/workflows/development-and-production#production-and-testing-environments). ## Adding Prisma Migrate to an existing project The steps involved in **adding Prisma Migrate to your existing project** are: 1. Introspect your database to update your Prisma schema 1. Create a baseline migration 1. Update your schema or migration to workaround features not supported by Prisma Schema Language 1. Apply the baseline migration 1. Commit the migration history and Prisma schema ### Introspect to create or update your Prisma schema Make sure your Prisma schema is in sync with your database schema. This should already be true if you are using a previous version of Prisma Migrate. 1. Introspect the database to make sure that your Prisma schema is up-to-date: ```terminal prisma db pull ``` ### Create a baseline migration Baselining is the process of initializing a migration history for a database that: - Existed before you started using Prisma Migrate - Contains data that must be maintained (like production), which means that the database cannot be reset Baselining tells Prisma Migrate to assume that one or more migrations have **already been applied**. This prevents generated migrations from failing when they try to create tables and fields that already exist. To create a baseline migration: 1. If you have a `prisma/migrations` folder, delete, move, rename, or archive this folder. 1. Run the following command to create a `migrations` directory inside with your preferred name. This example will use `0_init` for the migration name: ```terminal mkdir -p prisma/migrations/0_init ``` :::note The `0_` is important because Prisma Migrate applies migrations in a [lexicographic order](https://en.wikipedia.org/wiki/Lexicographic_order). You can use a different value such as the current timestamp. :::: 1. Generate a migration and save it to a file using `prisma migrate diff`: ```terminal no-lines npx prisma migrate diff \ --from-empty \ --to-schema-datamodel prisma/schema.prisma \ --script > prisma/migrations/0_init/migration.sql ``` 1. Review the generated migration. ### Work around features not supported by Prisma Schema Language To include [unsupported database features](/orm/prisma-migrate/workflows/unsupported-database-features) that already exist in the database, you must replace or modify the initial migration SQL: 1. Open the `migration.sql` file generated in the [Create a baseline migration](#create-a-baseline-migration) section. 1. Modify the generated SQL. For example: - If the changes are minor, you can append additional custom SQL to the generated migration. The following example creates a partial index: ```sql /* Generated migration SQL */ --add-start CREATE UNIQUE INDEX tests_success_constraint ON posts (subject, target) WHERE success; --add-end ``` - If the changes are significant, it can be easier to replace the entire migration file with the result of a database dump ([`mysqldump`](https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html), [`pg_dump`](https://www.postgresql.org/docs/12/app-pgdump.html)). When using `pg_dump` for this, you'll need to updade the `search_path` as follows with this command: `SELECT pg_catalog.set_config('search_path', '', false);`; otherwise you'll run into the following error: `The underlying table for model '_prisma_migrations' does not exist.` ` :::info Note that the order of the tables matters when creating all of them at once, since foreign keys are created at the same step. Therefore, either re-order them or move constraint creation to the last step after all tables are created, so you won't face `can't create constraint` errors ::: ### Apply the initial migrations To apply your initial migration(s): 1. Run the following command against your database: ```terminal npx prisma migrate resolve --applied 0_init ``` 1. Review the database schema to ensure the migration leads to the desired end-state (for example, by comparing the schema to the production database). The new migration history and the database schema should now be in sync with your Prisma schema. ### Commit the migration history and Prisma schema Commit the following to source control: - The entire migration history folder - The `schema.prisma` file ## Going further - Refer to the [Deploying database changes with Prisma Migrate](/orm/prisma-client/deployment/deploy-database-changes-with-prisma-migrate) guide for more on deploying migrations to production. - Refer to the [Production Troubleshooting](/orm/prisma-migrate/workflows/patching-and-hotfixing#fixing-failed-migrations-with-migrate-diff-and-db-execute) guide to learn how to debug and resolve failed migrations in production using `prisma migrate diff`, `prisma db execute` and/ or `prisma migrate resolve`. --- # Overview URL: https://www.prisma.io/docs/orm/prisma-migrate/understanding-prisma-migrate/overview
**Does not apply for MongoDB**
Instead of `migrate dev` and related commands, use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) for [MongoDB](/orm/overview/databases/mongodb).
Prisma Migrate enables you to: - Keep your database schema in sync with your [Prisma schema](/orm/prisma-schema) as it evolves _and_ - Maintain existing data in your database Prisma Migrate generates [a history of `.sql` migration files](/orm/prisma-migrate/understanding-prisma-migrate/migration-histories), and plays a role in both [development and production](/orm/prisma-migrate/workflows/development-and-production). Prisma Migrate can be considered a _hybrid_ database schema migration tool, meaning it has both of _declarative_ and _imperative_ elements: - Declarative: The data model is described in a declarative way in the [Prisma schema](/orm/prisma-schema). Prisma Migrate generates SQL migration files from that data model. - Imperative: All generated SQL migration files are fully customizable. Prisma Migrate hence provides the flexibility of an imperative migration tool by enabling you to modify what and how migrations are executed (and allows you to run custom SQL to e.g. make use of native database feature, perform data migrations, ...). :::tip If you are prototyping, consider using the [`db push`](/orm/reference/prisma-cli-reference#db-push) command - see [Schema prototyping with `db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) for examples. ::: See the [Prisma Migrate reference](/orm/reference/prisma-cli-reference#prisma-migrate) for detailed information about the Prisma Migrate CLI commands. --- # Mental model URL: https://www.prisma.io/docs/orm/prisma-migrate/understanding-prisma-migrate/mental-model This guide provides a conceptual overview of database migrations using Prisma Migrate when working with relational databases. It covers: what database migrations are, their value, and what Prisma Migrate is and how you can evolve your database schema with Prisma Migrate in different environments. **If you are working with MongoDB, use `prisma db push` to evolve your schema.** ## What are database migrations? Database migrations are a controlled set of changes that modify and evolve the structure of your database schema. Migrations help you transition your database schema from one state to another. For example, within a migration you can create or remove tables and columns, split fields in a table, or add types and constraints to your database. ### Patterns for evolving database schemas This section describes general schema migration patterns for evolving database schemas. The two main schema migration patterns are: - **Model/Entity-first migration:** with this pattern, you define the structure of the database schema with code and then use a migration tool to generate the SQL, for example, for syncing your application and database schema. ![Model-first migration flow](./mental-model-illustrations/entity-first-migration-flow.png) - **Database-first migration:** with this pattern, you define the structure of your database and apply it to your database using SQL. You then _introspect_ the database to generate the code that describes the structure of your database to sync your application and database schema. ![Database-first migration flow](./mental-model-illustrations/database-first-migration-flow.png) :::info **Note** For simplicity, we chose the terminology above to describe the different patterns for evolving database schemas. Other tools and libraries may use different terminology to describe the different patterns. ::: The migration files (SQL) should ideally be stored together with your application code. They should also be tracked in version control and shared with the rest of the team working on the application. Migrations provide _state management_ which helps you to track the state of the database. Migrations also allow you to replicate the state of a database at a specific point in time which is useful when collaborating with other members of the team, e.g. switching between different branches. For further information on database migrations, see the [Prisma Data Guide](https://www.prisma.io/dataguide/types/relational/what-are-database-migrations). ## What is Prisma Migrate? Prisma Migrate is a database migration tool that supports the _model/ entity-first_ migration pattern to manage database schemas in your local environment and in production. The workflow when using Prisma Migrate in your project would be iterative and look like this: **Local development environment (Feature branch)** 1. Evolve your Prisma schema 1. Use either [`prisma migrate dev`](#track-your-migration-history-with-prisma-migrate-dev) or [`prisma db push`](#prototype-your-schema) to sync your Prisma schema with the database schema of your local development database **Preview/ staging environment(Feature pull request)** 1. Push your changes to the feature pull request 1. Use a CI system (e.g. GitHub Actions) to sync your Prisma schema and migration history with your preview database using `prisma migrate deploy` **Production (main branch)** 1. Merge your application code from the feature branch to your main branch 1. Use a CI system (e.g. GitHub Actions) to sync your Prisma schema and migration history with your production database using `prisma migrate deploy` ![Prisma Migrate workflow](./mental-model-illustrations/prisma-migrate-lifecycle.png) ## How Prisma Migrate tracks the migration state Prisma Migrate uses the following pieces of state to track the state of your database schema: - **Prisma schema**: your source of truth that defines the structure of the database schema. - **Migrations history**: SQL files in your `prisma/migrations` folder representing the history of changes made to your database schema. - **Migrations table**: `prisma_migrations` table in the database that stores metadata for migrations that have been applied to the database. - **Database schema**: the state of the database. ![Prisma Migrate "state management"](./mental-model-illustrations/prisma-migrate-state-mgt.png) ## Requirements when working with Prisma Migrate - Ideally, you should use one database per environment. For example, you might have a separate database for development, preview, and production environments. - The databases you use in development environments are disposable — you can easily create, use, and delete databases on demand. - The database configuration used in each environments should be consistent. This is important to ensure a certain migration that moves across the workflow yields the same changes to the database. - The Prisma schema serves as the source of truth — describing the shape of your [database schema](https://www.prisma.io/dataguide/intro/database-glossary#schema). ## Evolve your database schema with Prisma Migrate This section describes how you can evolve your database schema in different environments: development, staging, and production, using Prisma Migrate. ### Prisma Migrate in a development environment (local) #### Track your migration history with `prisma migrate dev` The [`prisma migrate dev`](/orm/reference/prisma-cli-reference#migrate-dev) command allows you to track the changes you make to your database. The `prisma migrate dev` command automatically generates SQL migration files (saved in `/prisma/migrations`) and applies them to the database. When a migration is applied to the database, the migrations table (`_prisma_migrations`) in your database is also updated. ![Prisma Migrate dev flow](./mental-model-illustrations/prisma-migrate-dev-flow.png) The `prisma migrate dev` command tracks the state of the database using the following pieces of state: - the Prisma schema - the migrations history - the migrations table - the database schema > **Note**: The pieces of state used to track the state of a migration are the same as the ones described in [how Prisma Migrate tracks the migration state](#how-prisma-migrate-tracks-the-migration-state) section. You can customize migrations before you apply them to the database using the `--create-only` flag. For example, you might want to edit a migration if you want to rename columns without incurring any data loss or load database extensions (in PostgreSQL) and database views (currently not supported). Under the hood, Prisma Migrate uses a [shadow database](/orm/prisma-migrate/understanding-prisma-migrate/shadow-database) to detect a [schema drift](/orm/prisma-migrate/understanding-prisma-migrate/shadow-database#detecting-schema-drift) and generate new migrations. > **Note**: `prisma migrate dev` is intended to be used only in development with a disposable database. If `prisma migrate dev` detects a schema drift or a migration history conflict, you will be prompted to reset (drop and recreate your database) your database to sync the migration history and the database schema.
Expand to see the shadow database explained using a cartoon ![A cartoon that shows how the shadow database works.](./shadow-database.png)
#### Resolve schema drifts A schema drift occurs when the expected database schema is different from what is in the migration history. For example, this can occur when you manually update the database schema without also updating the Prisma schema and `prisma/migrations` accordingly. For such instances, you can use the [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) command to compare your migration history and revert changes made to your database schema. ![Revert database schema with `migrate diff`](./mental-model-illustrations/prisma-migrate-diff-flow.png) You can use `migrate diff` to generate the SQL that either: - Reverts the changes made in the database schema to synchronize it with the current Prisma schema - Moves your database schema forward to apply missing changes from the Prisma schema and `/migrations` You can then apply the changes to your database using [`prisma db execute`](/orm/reference/prisma-cli-reference#db-execute) command. #### Prototype your schema The [`prisma db push`](/orm/reference/prisma-cli-reference#db-push) command allows you to sync your Prisma schema and database schema without persisting a migration (`/prisma/migrations`). The `prisma db push` command tracks the state of the database using the following pieces of state: - the Prisma schema - the database schema ![prisma db push development flow](./mental-model-illustrations/db-push-flow.png) The `prisma db push` command is useful when: - You want to **quickly prototype and iterate** on schema design locally without the need to deploy these changes to other environments such as other developers, or staging and production environments. - You are prioritizing reaching a **desired end-state** and not the changes or steps executed to reach that end-state (there is no way to preview changes made by `prisma db push`) - You do not need to control how schema changes impact data. There is no way to orchestrate schema and data migrations - if `prisma db push` anticipates that changes will result in data loss, you can either accept data loss with the `--accept-data-loss` option or stop the process - there is no way to customize the changes. If the `prisma db push` command detects destructive change to your database schema, it will prompt you to reset your database. For example, this will happen when you add a required field to a table with existing content without providing a default value. > A [schema drift](/orm/prisma-migrate/workflows/troubleshooting#schema-drift) occurs when your database schema is out of sync with your migrations history and migrations table. ### Prisma Migrate in a staging and production environment #### Sync your migration histories The [`prisma migrate deploy`](/orm/reference/prisma-cli-reference#migrate-deploy) command allows you to sync your migration history from your development environment with your database in your **staging or production environment**. Under the hood, the `migrate deploy` command: 1. Compares already applied migrations (captured `_prisma_migrations`) and the migration history (`/prisma/migrations`) 1. Applies pending migrations 1. Updates `_prisma_migrations` table with the new migrations ![Workflow of Prisma Migrate](../300-workflows/deploy-db.png) The command should be run in an automated CI/ CD environment, for example GitHub Actions. If you don't have a migration history (`/migrations`), i.e using `prisma db push`, you will have to continue using `prisma db push` in your staging and production environments. Beware of the changes being applied to the database schema as some of them might be destructive. For example, `prisma db push` can't tell when you're performing a column rename. It will prompt a database reset (drop and re-creation). --- # About migration histories URL: https://www.prisma.io/docs/orm/prisma-migrate/understanding-prisma-migrate/migration-histories This page explains how Prisma ORM uses migration histories to track changes to your schema. ## Migration history Your migration history is the story of the changes to your data model, and is represented by: - A `prisma/migrations` folder with a sub-folder and `migration.sql` file for each migration: ``` migrations/ └─ 20210313140442_init/ └─ migration.sql └─ 20210313140442_added_job_title/ └─ migration.sql ``` The `migrations` folder is the **source of truth** for the history of your data model. - A `_prisma_migrations` table in the database, which is used to check: - If a migration was run against the database - If an applied migration was deleted - If an applied migration was changed If you change or delete a migration (**not** recommended), the next steps depend on whether you are in a [development environment](/orm/prisma-migrate/workflows/development-and-production#development-environments) (and therefore using `migrate dev`) or a [production / testing environment](/orm/prisma-migrate/workflows/development-and-production#production-and-testing-environments) (and therefore using `migrate deploy`). ## Do not edit or delete migrations that have been applied In general, you **should not edit or delete** a migration that has already been applied. Doing so can lead to inconsistencies between development and production environment migration histories, which may have unforeseen consequences — even if the change does not _appear_ to break anything at first. The following scenario simulates a change that creates a seemingly harmless inconsistency: 1. Modify an **existing migration** that has **already been applied** in a development environment by changing the value of `VARCHAR(550)` to `VARCHAR(560)`: ```sql file=./prisma/migrations/20210310143435_default_value/migrations.sql -- AlterTable ALTER TABLE "Post" ALTER COLUMN "content" SET DATA TYPE VARCHAR(560); ``` After making this change, the end state of the migration history no longer matches the Prisma schema, which still has `@db.VarChar(550)`. 1. Running `prisma migrate dev` results in an error because a migration has been changed and suggests resetting the database. 1. Run `prisma migrate reset` - Prisma Migrate resets the database and replays all migrations, including the migration you edited. 1. After applying all existing migrations, Prisma Migrate compares the end state of the migration history to the Prisma schema and detects a discrepancy: - Prisma schema has `@db.VarChar(550)` - Database schema has `VARCHAR(560)` 1. Prisma Migrate generates a new migration to change the value back to `550`, because the end state of the migration history should match the Prisma schema. 1. From now on, when you use `prisma migrate deploy` to deploy migrations to production and test environments, Prisma Migrate will always **warn you** that migration histories do not match (and continue to warn you each time you run the command ) - even though the schema end states match: ``` 6 migrations found in prisma/migrations WARNING The following migrations have been modified since they were applied: 20210310143435_change_type ``` A change that does not appear to break anything after a `migrate reset` can hide problems - you may end up with a bug in production that you cannot replicate in development, or the other way around - particularly if the change concerns a highly customized migration. If Prisma Migrate reports a missing or edited migration that has already been applied, we recommend fixing the **root cause** (restoring the file or reverting the change) rather than resetting. ## Committing the migration history to source control You must commit the entire `prisma/migrations` folder to source control. This includes the `prisma/migrations/migration_lock.toml` file, which is used to detect if you have [attempted to change providers](/orm/prisma-migrate/understanding-prisma-migrate/limitations-and-known-issues#you-cannot-automatically-switch-database-providers). Source-controlling the `schema.prisma` file is not enough - you must include your migration history. This is because: - As you start to [customize migrations](/orm/prisma-migrate/workflows/development-and-production#customizing-migrations), your migration history contains **information that cannot be represented in the Prisma schema**. For example, you can customize a migration to mitigate data loss that would be caused by a breaking change. - The `prisma migrate deploy` command, which is used to deploy changes to staging, testing, and production environments, _only_ runs migration files. It does not use the Prisma schema to fetch the models. --- # About the shadow database URL: https://www.prisma.io/docs/orm/prisma-migrate/understanding-prisma-migrate/shadow-database The shadow database is a second, _temporary_ database that is **created and deleted automatically**\* each time you run `prisma migrate dev` and is primarily used to **detect problems** such as schema drift or potential data loss of the generated migration. [`migrate diff` command](/orm/reference/prisma-cli-reference#migrate-diff) also requires a shadow database when diffing against a local `migrations` directory with `--from-migrations` or `--to-migrations`. * If your database does not allow creation and deleting of databases (e.g. in a cloud-hosted environment), you need to [create and configure the shadow database manually](#cloud-hosted-shadow-databases-must-be-created-manually). The shadow database is **not** required in production, and is not used by production-focused commands such as `prisma migrate resolve` and `prisma migrate deploy`. A shadow database is never used for MongoDB as `migrate dev` is not used there. ## How the shadow database works When you run `prisma migrate dev` to create a new migration, Prisma Migrate uses the shadow database to: - [Detect schema drift](#detecting-schema-drift), which means checking that no **unexpected changes** have been made to the development database - [Generate new migrations](#generating-new-migrations) and evaluate if those could lead to **data loss** when applied
🎨 Expand to see the shadow database explained as a cartoon. ![A cartoon that shows how the shadow database works.](./shadow-database.png)
### Detecting schema drift To detect drift in development, Prisma Migrate: 1. Creates a fresh copy of the shadow database (or performs a soft reset if the shadow database is configured via [`shadowDatabaseUrl`](/orm/reference/prisma-schema-reference#datasource)) 1. Reruns the **current**, existing migration history in the shadow database. 1. **Introspects** the shadow database to generate the 'current state' of your Prisma schema. 1. Compares the end state of the current migration history to the development database. 1. Reports **schema drift** if the end state of the current migration history (via the shadow database) does not match the development database (for example, due to a manual change) If Prisma Migrate does not detect schema drift, it moves on to [generating new migrations](#generating-new-migrations). > **Note**: The shadow database is not responsible for checking if a migration file has been **edited or deleted**. This is done using the `checksum` field in the `_prisma_migrations` table. If Prisma Migrate detects schema drift, it outputs detailed information about which parts of the database have drifted. The following example output could be shown when the development database has been modified manually: The `Color` enum is missing the expected variant `RED` and includes the unexpected variant `TRANSPARENT`: ``` [*] Changed the `Color` enum [+] Added variant `TRANSPARENT` [-] Removed variant `RED` ``` ### Generating new migrations Assuming Prisma Migrate did not [detect schema drift](#detecting-schema-drift), it moves on to generating new migrations from Prisma schema changes. To generate new migrations, Prisma Migrate: 1. Calculates the target database schema as a function of the current Prisma schema. 1. Compares the end state of the existing migration history and the target schema, and generates steps to get from one to the other. 1. Renders these steps to a SQL string and saves it in the new migration file. 1. Evaluate data loss caused by the SQL and warns about that. 1. Applies the generated migration to the development database (assuming you have not specified the `--create-only` flag) 1. Drops the shadow database (shadow databases configured via [`shadowDatabaseUrl`](/orm/reference/prisma-schema-reference#datasource) are not dropped, but are reset at the start of the `migrate dev` command) ## Manually configuring the shadow database In some cases it might make sense (e.g. when [creating and dropping databases is not allowed on cloud-hosted databases](#cloud-hosted-shadow-databases-must-be-created-manually)) to manually define the connection string and name of the database that should be used as the shadow database for `migrate dev`. In such a case you can: 1. Create a dedicated database that should be used as the shadow database 2. Add the connection string of that database your environment variable `SHADOW_DATABASE_URL` (or `.env` file) 3. Add the [`shadowDatabaseUrl`](/orm/reference/prisma-schema-reference#datasource) field reading this environment variable: ```prisma highlight=4;normal datasource db { provider = "postgresql" url = env("DATABASE_URL") //highlight-next-line shadowDatabaseUrl = env("SHADOW_DATABASE_URL") } ``` > **Important**: Do not use the exact same values for `url` and `shadowDatabaseUrl` as that might delete all the data in your database. ## Cloud-hosted shadow databases must be created manually Some cloud providers do not allow you to drop and create databases with SQL. Some require to create or drop the database via an online interface, and some really limit you to 1 database. If you **develop** in such a cloud-hosted environment, you must: 1. Create a dedicated cloud-hosted shadow database 2. Add the URL to your environment variable `SHADOW_DATABASE_URL` 3. Add the [`shadowDatabaseUrl`](/orm/reference/prisma-schema-reference#datasource) field reading this environment variable: ```prisma highlight=4;normal datasource db { provider = "postgresql" url = env("DATABASE_URL") //highlight-next-line shadowDatabaseUrl = env("SHADOW_DATABASE_URL") } ``` > **Important**: Do not use the same values for `url` and `shadowDatabaseUrl`. ## Shadow database user permissions In order to create and delete the shadow database when using `migrate dev`, Prisma Migrate currently requires that the database user defined in your `datasource` has permission to **create databases**. | Database | Database user requirements | | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | SQLite | No special requirements. | | MySQL/MariaDB | Database user must have `CREATE, ALTER, DROP, REFERENCES ON *.*` privileges | | PostgreSQL | The user must be a super user or have `CREATEDB` privilege. See `CREATE ROLE` ([PostgreSQL official documentation](https://www.postgresql.org/docs/12/sql-createrole.html)) | | Microsoft SQL Server | The user must be a site admin or have the `SERVER` securable. See the [official documentation](https://learn.microsoft.com/en-us/sql/relational-databases/security/permissions-database-engine?view=sql-server-ver15). | > If you use a cloud-hosted database for development and can not use these permissions, see: [Cloud-hosted shadow databases](#cloud-hosted-shadow-databases-must-be-created-manually) > Note: The automatic creation of shadow databases is disabled on Azure SQL for example. Prisma Migrate throws the following error if it cannot create the shadow database with the credentials your connection URL supplied: ``` Error: A migration failed when applied to the shadow database Database error: Error querying the database: db error: ERROR: permission denied to create database ``` To resolve this error: - If you are working locally, we recommend that you update the database user's privileges. - If you are developing against a database that does not allow creating and dropping databases (for any reason) see [Manually configuring the shadow database](#manually-configuring-the-shadow-database) - If you are developing against a cloud-based database (for example, on Heroku, Digital Ocean, or Vercel Postgres) see: [Cloud-hosted shadow databases](#cloud-hosted-shadow-databases-must-be-created-manually). - If you are developing against a cloud-based database (for example, on Heroku, Digital Ocean, or Vercel Postgres) and are currently **prototyping** such that you don't care about generated migration files and only need to apply your Prisma schema to the database schema, you can run [`prisma db push`](/orm/reference/prisma-cli-reference#db) instead of the `prisma migrate dev` command. > **Important**: The shadow database is _only_ required in a development environment (specifically for the `prisma migrate dev` command) - you **do not** need to make any changes to your production environment. --- # Limitations and known issues URL: https://www.prisma.io/docs/orm/prisma-migrate/understanding-prisma-migrate/limitations-and-known-issues The following limitations apply to Prisma Migrate. ## MongoDB connector not supported Prisma Migrate does not currently support the MongoDB connector. ## You cannot automatically switch database providers Prisma Migrate generates SQL files that are specific to your provider. This means that you cannot use the same migration files for PostgreSQL in production and SQLite in development, because the syntax in the migrations will be incompatible. In [2.15.0](https://github.com/prisma/prisma/releases/2.15.0) and later, Prisma Migrate detects when the migrations do not match the configured provider and prints a helpful error message. For example, if your migrations are for a PostgreSQL database but you are using a `provider` is set to `mysql`: ``` Error: P3014 The datasource provider `postgresql` specified in your schema does not match the one specified in the migration_lock.toml, mysql. Please remove your current migration directory and start a new migration history with prisma migrate dev. ``` In order to manually switch the database provider, you must: - Change the `provider` and `url` parameters in the `datasource` block in your schema - Archive or remove your existing migration history - there must not be a `./prisma/migrations` folder - Run `prisma migrate dev` to start a new migration history The last step creates a new initial migration that goes from an empty database to your current `schema.prisma`. Be aware that: - This migration will _only_ contain what is reflected in your `schema.prisma`. If you manually edited your previous migration files to add custom SQL you will need to again add this yourself. - The newly created database using the new provider will not contain any data. ## Data loss when resetting database In a development environment, Prisma Migrate sometimes prompts you to reset the database. Resetting drops and recreates the database, which results in data loss. The database is reset when: - You call `prisma migrate reset` explicitly - You call `prisma migrate dev` and Prisma Migrate detects drift in the database or a migration history conflict The `prisma migrate dev` and `prisma migrate reset` commands are designed to be used **in development only**, and should not affect production data. When the database is reset, if Prisma Migrate detects a seed script in `package.json`, it will trigger seeding. > **Note**: For a simple and integrated way to re-create data when the database is reset, check out our [seeding guide](/orm/prisma-migrate/workflows/seeding). ## Prisma Migrate and PgBouncer You might see the following error if you attempt to run Prisma Migrate commands in an environment that uses PgBouncer for connection pooling: ```bash Error: undefined: Database error Error querying the database: db error: ERROR: prepared statement "s0" already exists ``` See [Prisma Migrate and PgBouncer workaround](/orm/prisma-client/setup-and-configuration/databases-connections/pgbouncer) for further information and a workaround. Follow [GitHub issue #6485](https://github.com/prisma/prisma/issues/6485) for updates. ## Prisma Migrate in non-interactive environments Prisma ORM detects when you run CLI commands in non-interactive environments, such as Docker, from Node scripts or in bash shells. When this happens a warning displays, indicating that the environment is non-interactive and the `migrate dev` command is not supported. To ensure the Docker environment picks up the command, run the image in `interactive` mode so that it reacts to the `migrate dev` command. ```terminal docker run --interactive --tty # or docker -it # Example usage docker run -it node ``` --- # Legacy Prisma Migrate URL: https://www.prisma.io/docs/orm/prisma-migrate/understanding-prisma-migrate/legacy-migrate > **Important!** This page documents legacy Prisma Migrate (Experimental) available in version 2.12.0 and earlier. [Prisma Migrate](/orm/prisma-migrate) is available in version [2.13.0](https://github.com/prisma/prisma/releases/tag/2.13.0) and Generally Available in [2.19.0](https://github.com/prisma/prisma/releases/tag/2.19.0). Legacy Prisma Migrate is a tool that lets you _change your database schema_, e.g. by creating new tables or adding columns to existing tables. These changes are called _schema migrations_. legacy Prisma Migrate is available as part of the [Prisma CLI](/orm/tools/prisma-cli#installation) via the `legacy Prisma Migrate` command. ## Documentation ### Legacy Prisma Migrate vs the `db push` command If you want to prototype or iterate on a schema design in a development environment, consider the [`db push` command](/orm/reference/prisma-cli-reference#db-push). ### Legacy Prisma Migrate vs SQL migrations Legacy Prisma Migrate is a _declarative_ migration system, as opposed to SQL which can be considered _imperative_: - **SQL (imperative)**: Provide the individual _steps_ to get from the current schema to the desired schema. - **legacy Prisma Migrate (declarative)**: Define the desired schema as a [Prisma schema data model](/orm/prisma-schema/data-model/models) (legacy Prisma Migrate takes care of generating the necessary _steps_). Here's a quick comparison. Assume you have the following scenario: 1. You need to create the `User` table to store user information (name, email, ...) 1. Create two new tables `Post` and `Profile` with foreign keys to `User` 1. Add a new column with a default value to the `Post` table #### SQL In SQL, you'd have to send three subsequent SQL statements to account for this scenario: ##### 1. Create the `User` table to store user information (name, email, ...) ```sql CREATE TABLE "User" ( id SERIAL PRIMARY KEY, name VARCHAR(255), email VARCHAR(255) NOT NULL ); ``` ##### 2. Create two new tables `Post` and `Profile` with foreign keys to `User` ```sql CREATE TABLE "Profile" ( id SERIAL PRIMARY KEY, bio TEXT NOT NULL, "user" integer NOT NULL UNIQUE, FOREIGN KEY ("user") REFERENCES "User"(id) ); CREATE TABLE "Post" ( id SERIAL PRIMARY KEY, title VARCHAR(255) NOT NULL, author integer NOT NULL, FOREIGN KEY (author) REFERENCES "User"(id) ); ``` ##### 3. Add a new column with a default value to the `Post` table ```sql ALTER TABLE "Post" ADD COLUMN published BOOLEAN DEFAULT false; ``` #### legacy Prisma Migrate With legacy Prisma Migrate, you write the desired database schema in the form of a [Prisma schema data model](/orm/prisma-schema/data-model/models) inside your [Prisma schema file](/orm/prisma-schema). To map the data model to your database schema, you then have to run these two commands: ```terminal prisma migrate save --experimental prisma migrate up --experimental ``` The first command _saves_ a new migration to the `prisma/migrations` directory in the file system of your project and updates the `_Migration` table in your database. Each time you run this command to save a new migration, it creates a dedicated directory inside of `prisma/migrations` for that specific migration, which will have its own `README.md` file containing detailed information about the migration (e.g. the generated SQL statements which will be executed when you run `legacy Prisma Migrate up`). The second command _executes_ the migration against your database. ##### 1. Create the `User` table to store user information (name, email, ...) Add the model to your Prisma schema: ```prisma model User { id Int @id @default(autoincrement()) name String? email String @unique } ``` Now run the two commands mentioned above: ```terminal prisma migrate save --experimental prisma migrate up --experimental ``` ##### 2. Create two new tables `Post` and `Profile` with foreign keys to `User` Add two models with [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) to your Prisma schema: ```prisma model User { id Int @id @default(autoincrement()) name String? email String @unique posts Post[] profile Profile? } model Profile { id Int @id @default(autoincrement()) bio String user User @relation(fields: [userId], references: [id]) userId Int } model Post { id Int @id @default(autoincrement()) title String author User @relation(fields: [authorId], references: [id]) authorId Int } ``` Notice that in addition to the [annotated relation fields](/orm/prisma-schema/data-model/relations#annotated-relation-fields) and its relation scalar field (which represent the foreign keys), you must also specify the Prisma-level [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) on the other side of the relation. Now run the two commands mentioned above: ```terminal prisma migrate save --experimental prisma migrate up --experimental ``` ##### 3. Add a new column with default value to the `Post` table Add a [field](/orm/prisma-schema/data-model/models#defining-fields) to the `Post` model: ```prisma model User { id Int @id @default(autoincrement()) name String? email String @unique posts Post[] profile Profile? } model Profile { id Int @id @default(autoincrement()) bio String user User @relation(fields: [userId], references: [id]) userId Int } model Post { id Int @id @default(autoincrement()) title String published Boolean @default(false) authorId Int author User @relation(fields: [authorId], references: [id]) } ``` Now run the two commands mentioned above: ```terminal prisma migrate save --experimental prisma migrate up --experimental ``` ### Supported operations The following table shows which SQL operations are currently supported by legacy Prisma Migrate. | Operation | SQL | Supported | | :-------------------------------- | :------------------------------ | :-----------------------------------------------------------------------------------: | | Create a new table | `CREATE TABLE` | ✔️ | | Rename an existing table | `ALTER TABLE` + `RENAME` | No | | Delete an existing table | `DROP TABLE` | ✔️ | | Add a column to an existing table | `ALTER TABLE` + `ADD COLUMN` | ✔️ | | Rename an existing column | `ALTER TABLE` + `RENAME COLUMN` | No | | Delete an existing column | `ALTER TABLE` + `DROP COLUMN` | ✔️ | | Set primary keys (IDs) | `PRIMARY KEY` | ✔️ | | Define relations (foreign keys) | `FOREIGN KEY` + `REFERENCES` | ✔️ | | Make columns optional/required | `NOT NULL` | ✔️ | | Set unique constraints | `UNIQUE` | ✔️ | | Set default values | `DEFAULT` | ✔️ | | Define enums | `ENUM` | ✔️ | | Create indexes | `CREATE INDEX` | ✔️ | | Cascading deletes | `ON DELETE` | No (workaround: manually add in SQL and introspect) | | Cascading updates | `ON UPDATE` | No | | Data validation | `CHECK` | No ([workaround](/orm/more/help-and-troubleshooting/check-constraints)) | Note that this table assumes that the operation is also supported by the underlying database. For example, `ENUM` is not supported in SQLite. This means that you also can't use `enum` when using legacy Prisma Migrate. ### Migration history legacy Prisma Migrate stores the migration history of your project in two places: - A directory called `migrations` on your file system - A table called `_Migration` in your database #### The `migrations` directory The `migrations` directory stores information about the migrations that have been or will be executed against your database. You should never make any manual changes to the files in `migrations`. The only way to change the content of this directory should be using the `legacy Prisma Migrate save` command. The `migrations` directory should be checked into version control (e.g. Git). #### The `_Migration` table The `_Migration` table additionally stores information about each migration that was ever executed against the database by legacy Prisma Migrate. ### Typical workflow With **legacy Prisma Migrate**, the workflow looks slightly different: 1. Manually adjust your [Prisma schema data model](/orm/prisma-schema/data-model/models) 1. Migrate your database using the `legacy Prisma Migrate` CLI commands 1. (Re-)generate Prisma Client 1. Use Prisma Client in your application code to access your database ### Troubleshooting Since legacy Prisma Migrate is currently Experimental, you might end up in a state where the `migrations` directory and/or the `_Migrations` table are out of sync with the actual state of the database. In these cases, it often helps to "reset" legacy Prisma Migrate by deleting the `migrations` folder and deleting all entries from the `_Migration` table. #### Delete the `migrations` directory ```terminal rm -rf migrations ``` #### Delete all entries from the `_Migration` table ```sql TRUNCATE _Migration; ``` ## CLI Reference > Warning: The `migrate` command is still considered Experimental. As such, there are no guarantees about API stability or production-readiness. Access to this command is provided for evaluation and experimentation. To access Experimental commands, you must add the `--experimental` flag. The `migrate` command creates and manages database migrations. It can be used to create, apply, and rollback database schema updates in a controlled manner. The `migrate` command includes a number of subcommands to specify the desired action. ### `migrate save` Saves a migration that defines the steps necessary to update your current schema. #### Prerequisites Before using the `migrate save` command, you must define a valid [`datasource`](/orm/prisma-schema/overview/data-sources) within your `schema.prisma` file. For example, the following `datasource` defines a SQLite database file within the current directory: ```prisma datasource db { provider = "sqlite" url = "file:my-database.db" } ``` #### Options The `migrate save` command recognizes the following options to modify its behavior: | Option | Required | Description | Default | | ------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | | `--experimental` | Yes | Enables use of Experimental commands. | | | `-n`, `--name` | No | The name of the migration. If not provided, `migrate save` will prompt you for a name. | Timestamp `20200618145356` | | `-c`, `--create-db` | No | Create the database if it does not exist. | | | `-p`, `--preview` | No | Preview the migration that would be created without writing any changes to the filesystem. | | | `--schema` | No | Specifies the path to the desired `schema.prisma` file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`, `./prisma/schema.prisma` | #### Generated Assets The `migrate save` command generates the following directories and files as necessary: - `migrations`: A directory within the current project to store migrations. This directory will be created if it does not exist. - `migrations/migrate.lock`: A lock file created specifying the current migration applied to the database. This file will be created if it does not exist. - `migrations/`: A directory for a specific migration. The migration name is derived from the timestamp when it was created followed by a hyphen and the migration name provided by the user. - `migrations//README.md`: A human-readable description of the migration including metadata like when the migration was created and by who, a list of the actual migration changes and a diff of the changes that are made to the `schema.prisma` file. - `migrations//schema.prisma`: The schema that will be created if the migration is applied to the project. - `migrations//steps.json`: An [alternative representation](https://github.com/prisma/specs/tree/master/migrate#step) of the migration steps that will be applied. #### Examples ##### Create a new migration ```terminal prisma migrate save --experimental ``` The command will prompt you for a name for the migration since one was not provided on the command line. After creating the migration, the contents of the generated `schema.prisma` file are displayed. ##### Create a migration with a specific name ```terminal prisma migrate save --name "First migration" --experimental ``` ##### Create the database if it does not already exist ```terminal prisma migrate save --create-db --experimental ``` ##### Preview the migration that would be created by running the `migrate save` command ```terminal prisma migrate save --preview --experimental ``` ### `migrate up` Migrate the database up to a specific state. #### Prerequisites Before using the `migrate up` command, you must define a valid [`datasource`](/orm/prisma-schema/overview/data-sources) within your `schema.prisma` file. For example, the following `datasource` defines a SQLite database file within the current directory: ```prisma datasource db { provider = "sqlite" url = "file:my-database.db" } ``` #### Arguments The point to migrate the database up to can be defined in any of the following three ways: | Argument | Required | Description | Default | | --------- | -------- | ---------------------------------------------------------------------------------- | ------- | | increment | No | Specifies the number of forward migrations to apply. | latest | | name | No | Specifies where to migrate to using the name of the final migration to apply. | latest | | timestamp | No | Specifies where to migrate to using the timestamp of the final migration to apply. | latest | #### Options Additionally, the following options modify the behavior of the `migrate up` command: | Option | Required | Description | Default | | ------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | | `--experimental` | Yes | Enables use of Experimental commands | | | `-c`, `--create-db` | No | Create the database if it does not exist. | | | `-p`, `--preview` | No | Preview the migration that would be created without writing any changes to the filesystem. | | | `--schema` | No | Specifies the path to the desired `schema.prisma` file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`, `./prisma/schema.prisma` | | `--auto-approve` | No | Skip interactive approval before migrating. | | #### Examples ##### Migrate the database up to the latest available migration ```terminal prisma migrate up --experimental ``` ##### Apply the next two migrations to the database ```terminal prisma migrate up 2 --experimental ``` ##### Apply all migrations necessary up to and including a migration by name ```terminal prisma migrate up "First migration" --experimental ``` ##### Apply all migrations necessary up to and including a migration by timestamp ```terminal prisma migrate up 20200223181448 --experimental ``` ##### Create the database if it does not already exist before applying the migrations ```terminal prisma migrate up --create-db --experimental ``` ##### Preview the migration that would be applied by running the `migrate up` command ```terminal prisma migrate up --preview --experimental ``` ### `migrate down` Migrate the database down to a specific state. #### Prerequisites Before using the `migrate down` command, you must define a valid [`datasource`](/orm/prisma-schema/overview/data-sources) within your `schema.prisma` file. For example, the following `datasource` defines a SQLite database file within the current directory: ```prisma datasource db { provider = "sqlite" url = "file:my-database.db" } ``` #### Arguments The point to migrate back to can be defined in any of the following three ways: | Argument | Required | Description | Default | | --------- | -------- | --------------------------------------------------------------------------------------- | ------- | | decrement | No | Specifies the number of backwards migrations to apply. | 1 | | name | No | Specifies where to migrate back to using the name of the final migration to apply. | | timestamp | No | Specifies where to migrate back to using the timestamp of the final migration to apply. | #### Options Additionally, the following options modify the behavior of the `migrate down` command: | Option | Required | Description | Default | | ----------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | | `--experimental` | Yes | Enables use of Experimental commands | | | `-p`, `--preview` | No | Preview the migration that would be created without writing any changes to the filesystem. | | | `--schema` | No | Specifies the path to the desired `schema.prisma` file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`, `./prisma/schema.prisma` | #### Examples ##### Migrate the database backwards by a single migration ```terminal prisma migrate down --experimental ``` ##### Migrate the database backwards by two migrations ```terminal prisma migrate down 2 --experimental ``` ##### Migrate backwards through all migrations up to and including a migration by name ```terminal prisma migrate down "First migration" --experimental ``` ##### Migrate backwards through all migrations up to and including a migration by timestamp ```terminal prisma migrate down 20200223181448 --experimental ``` ##### Preview the migration that would be applied by running the `migrate down` command ```terminal prisma migrate down --preview --experimental ``` --- # Understanding Prisma Migrate URL: https://www.prisma.io/docs/orm/prisma-migrate/understanding-prisma-migrate/index ## In this section --- # Seeding URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/seeding This guide describes how to seed your database using Prisma Client and Prisma ORM's integrated seeding functionality. Seeding allows you to consistently re-create the same data in your database and can be used to: - Populate your database with data that is required for your application to start, such as a default language or currency. - Provide basic data for validating and using your application in a development environment. This is particularly useful if you are using Prisma Migrate, which sometimes requires resetting your development database. ## How to seed your database in Prisma ORM Prisma ORM's integrated seeding functionality expects a command in the `"seed"` key in the `"prisma"` key of your `package.json` file. This can be any command, `prisma db seed` will just execute it. In this guide and as a default, we recommend writing a seed script inside your project's `prisma/` folder and starting it with the command.
```json "prisma": { "seed": "ts-node prisma/seed.ts" }, ```
With TypeScript,`ts-node` does transpiling and typechecking by default; typechecking can be disabled with the following flag `--transpile-only`. Example: `"seed": "ts-node --transpile-only prisma/seed.ts"` This can be useful to reduce memory usage (RAM) and increase execution speed of the seed script.

```json "prisma": { "seed": "node prisma/seed.js" }, ```
## Integrated seeding with Prisma Migrate Database seeding happens in two ways with Prisma ORM: manually with `prisma db seed` and automatically in `prisma migrate reset` and (in some scenarios) `prisma migrate dev`. With `prisma db seed`, _you_ decide when to invoke the seed command. It can be useful for a test setup or to prepare a new development environment, for example. Prisma Migrate also integrates seamlessly with your seeds, assuming you follow the steps in the section below. Seeding is triggered automatically when Prisma Migrate resets the development database. Prisma Migrate resets the database and triggers seeding in the following scenarios: - You manually run the `prisma migrate reset` CLI command. - The database is reset interactively in the context of using `prisma migrate dev` - for example, as a result of migration history conflicts or database schema drift. - The database is actually created by `prisma migrate dev`, because it did not exist before. When you want to use `prisma migrate dev` or `prisma migrate reset` without seeding, you can pass the `--skip-seed` flag. ## Example seed scripts Here we suggest some specific seed scripts for different situations. You are free to customize these in any way, but can also use them as presented here: ### Seeding your database with TypeScript or JavaScript 1. Create a new file named `seed.ts`. This can be placed anywhere within your project's folder structure. The example below places it in the `/prisma` folder. 2. In the `seed.ts` file, import Prisma Client, initialize it and create some records. As an example, take the following Prisma schema with a `User` and `Post` model: ```prisma file=schema.prisma showLineNumbers model User { id Int @id @default(autoincrement()) email String @unique name String posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String published Boolean user User @relation(fields: [userId], references: [id]) userId Int } ``` Create some new users and posts in your `seed.ts` file: ```js file=seed.ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { const alice = await prisma.user.upsert({ where: { email: 'alice@prisma.io' }, update: {}, create: { email: 'alice@prisma.io', name: 'Alice', posts: { create: { title: 'Check out Prisma with Next.js', content: 'https://www.prisma.io/nextjs', published: true, }, }, }, }) const bob = await prisma.user.upsert({ where: { email: 'bob@prisma.io' }, update: {}, create: { email: 'bob@prisma.io', name: 'Bob', posts: { create: [ { title: 'Follow Prisma on Twitter', content: 'https://twitter.com/prisma', published: true, }, { title: 'Follow Nexus on Twitter', content: 'https://twitter.com/nexusgql', published: true, }, ], }, }, }) console.log({ alice, bob }) } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` 3. Add `typescript`, `ts-node` and `@types/node` development dependencies: ``` npm install -D typescript ts-node @types/node ``` 4. Add the `prisma.seed` field to your `package.json` file: ```json file=package.json highlight=5;normal { "name": "my-project", "version": "1.0.0", "prisma": { "seed": "ts-node prisma/seed.ts" }, "devDependencies": { "@types/node": "^14.14.21", "ts-node": "^9.1.1", "typescript": "^4.1.3" } } ``` Some projects may require you to add compile options. When using Next.js for example, you would setup your seed script like so: ```json file=package.json "prisma": { "seed": "ts-node --compiler-options {\"module\":\"CommonJS\"} prisma/seed.ts" }, ``` 5. To seed the database, run the `db seed` CLI command: ``` npx prisma db seed ``` 1. Create a new file named `seed.js`. This can be placed anywhere within your project's folder structure. The below example places it in the `/prisma` folder. 2. In the `seed.js` file, import Prisma Client, initialize it and create some records. As an example, take the following Prisma schema with a `User` and `Post` model: ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) email String @unique name String posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String published Boolean user User @relation(fields: [userId], references: [id]) userId Int } ``` Create some new users and posts in your `seed.js` file: ```js file=seed.js const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { const alice = await prisma.user.upsert({ where: { email: 'alice@prisma.io' }, update: {}, create: { email: 'alice@prisma.io', name: 'Alice', posts: { create: { title: 'Check out Prisma with Next.js', content: 'https://www.prisma.io/nextjs', published: true, }, }, }, }) const bob = await prisma.user.upsert({ where: { email: 'bob@prisma.io' }, update: {}, create: { email: 'bob@prisma.io', name: 'Bob', posts: { create: [ { title: 'Follow Prisma on Twitter', content: 'https://twitter.com/prisma', published: true, }, { title: 'Follow Nexus on Twitter', content: 'https://twitter.com/nexusgql', published: true, }, ], }, }, }) console.log({ alice, bob }) } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` 3. Add the `prisma.seed` to your `package.json` file: ```json file=package.json highlight=5;normal { "name": "my-project", "version": "1.0.0", "prisma": { "seed": "node prisma/seed.js" } } ``` 4. To seed the database, run the `db seed` CLI command: ``` npx prisma db seed ``` ### Seeding your database via raw SQL queries You can also make use of raw SQL queries in order to seed the database with data. While you can use a plain-text `.sql` file (such as a data dump) for that, it is often easier to place those raw queries, if they're of short size, into the `seed.js` file because it saves you the hassle of working out database connection strings and creating a dependency on a binary like `psql`. To seed additional data to the `schema.prisma` above, add the following to the `seed.js` (or `seed.ts`) file: ```js file=seed.js async function rawSql() { const result = await prisma.$executeRaw`INSERT INTO "User" ("id", "email", "name") VALUES (3, 'foo@example.com', 'Foo') ON CONFLICT DO NOTHING;` console.log({ result }) } ``` and chain this function to the promise calls, such as the following change towards the end of the file: ```js file=seed.js main() .then(rawSql) .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` ### Seeding your database via any language (with a Bash script) In addition to TypeScript and JavaScript, you can also use a Bash script (`seed.sh`) to seed your database in another language such as Go, or plain SQL.
The following example runs a Go script in the same folder as `seed.sh`:
```bash file=seed.sh #!/bin/sh # -e Exit immediately when a command returns a non-zero status. # -x Print commands before they are executed set -ex # Seeding command go run ./seed/ ```

The following example uses [psql](https://www.postgresql.org/docs/13/app-psql.html) to run a SQL script in the same folder as `seed.sh`:
```bash file=seed.sh #!/bin/sh # -e Exit immediately when a command returns a non-zero status. # -x Print commands before they are executed set -ex # Seeding command psql file.sql ```
### User-defined arguments > This feature is available from version 4.15.0 and later. `prisma db seed` allows you to define custom arguments in your seed file that you can pass to the `prisma db seed` command. For example, you could define your own arguments to seed different data for different environments or partially seeding data in some tables. Here is an example seed file that defines a custom argument to seed different data in different environments: ```js file="seed.js" import { parseArgs } from 'node:util' const options = { environment: { type: 'string' }, } async function main() { const { values: { environment }, } = parseArgs({ options }) switch (environment) { case 'development': /** data for your development */ break case 'test': /** data for your test environment */ break default: break } } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` You can then provide the `environment` argument when using `prisma db seed` by adding a [delimiter](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_02) — `--` —, followed by your custom arguments: ``` npx prisma db seed -- --environment development ``` ## Going further Here's a non-exhaustive list of other tools you can integrate with Prisma ORM in your development workflow to seed your database: - [Supabase community project](https://github.com/supabase-community/seed) - [Replibyte](https://www.replibyte.com/docs/introduction/) --- # Team development URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/team-development This guide has been moved to the [guides section](/guides/implementing-schema-changes). You can find the guide there. --- # Native database types URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/native-database-types Prisma Migrate translates the model defined in your [Prisma schema](/orm/prisma-schema) into features in your database. ![A diagram that shows a Prisma schema on the left (labeled: Prisma schema, models) and a database on the right (labeled: Database, tables). Two parallel arrows connect the schema and the database, showing how '@unique' maps to 'UNIQUE' and '@id' maps to 'PRIMARY KEY'.](../200-understanding-prisma-migrate/migrate-mapping.png) Every¹ feature in your [data model](/orm/prisma-schema/data-model/models) maps to a corresponding feature in the underlying database. **If you can define a feature in the Prisma schema, it is supported by Prisma Migrate.** For a complete list of Prisma schema features, refer to: - [Database features matrix](/orm/reference/database-features) for a list of database features and what they map to in the Prisma schema. - [Prisma schema reference](/orm/reference/prisma-schema-reference) for a list of all Prisma schema features, including field types, attributes, and functions. Prisma Migrate also supports mapping each field to a [specific native type](#mapping-fields-to-a-specific-native-type), and there are ways to [include features without a Prisma schema equivalent in your database](#handling-unsupported-database-features). :::note Comments and Prisma ORM-level functions (`uuid()` and `cuid()`) do not map to database features. ::: ## Mapping fields to a specific native type Each Prisma ORM type maps to a default underlying database type - for example, the PostgreSQL connector maps `String` to `text` by default. [Native database type attributes](/orm/prisma-schema/data-model/models#native-types-mapping) determines which _specific_ native type should be created in the database. **Note**: Some Prisma ORM types only map to a single native type. In the following example, the `name` and `title` fields have a `@db.VarChar(X)` type attribute: ```prisma highlight=8,14;normal datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) name String @db.VarChar(200) posts Post[] } model Post { id Int @id @default(autoincrement()) title String @db.VarChar(150) published Boolean @default(true) authorId Int author User @relation(fields: [authorId], references: [id]) } ``` Prisma Migrate uses the specified types when it creates a migration: ```sql highlight=4,10;normal -- CreateTable CREATE TABLE "User" ( "id" SERIAL, "name" VARCHAR(200) NOT NULL, PRIMARY KEY ("id") ); -- CreateTable CREATE TABLE "Post" ( "id" SERIAL, "title" VARCHAR(150) NOT NULL, "published" BOOLEAN NOT NULL DEFAULT true, "authorId" INTEGER NOT NULL, PRIMARY KEY ("id") ); -- AddForeignKey ALTER TABLE "Post" ADD FOREIGN KEY("authorId")REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE; ``` ### Mappings by Prisma ORM type For type mappings organized by Prisma ORM type, refer to the [Prisma schema reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) documentation. ### Mappings by database provider For type mappings organized by database provider, see: - [PostgreSQL mappings](/orm/overview/databases/postgresql#type-mapping-between-postgresql-and-prisma-schema) - [MySQL mappings](/orm/overview/databases/mysql#native-type-mappings) - [Microsoft SQL Server mappings](/orm/overview/databases/sql-server#type-mapping-between-microsoft-sql-server-to-prisma-schema) - [SQLite mappings](/orm/overview/databases/sqlite#type-mapping-between-sqlite-to-prisma-schema) ## Handling unsupported database features Prisma Migrate cannot automatically create database features that have no equivalent in Prisma Schema Language (PSL). For example, there is currently no way to define a stored procedure or a partial index in PSL. However, there are ways to add unsupported features to your database with Prisma Migrate: - [Handle unsupported field types](/orm/prisma-schema/data-model/unsupported-database-features#unsupported-field-types) (like `circle`) - [Handle unsupported features](/orm/prisma-schema/data-model/unsupported-database-features#unsupported-database-features), like stored procedures - [How to use native database functions](/orm/prisma-schema/data-model/unsupported-database-features#native-database-functions) --- # Native database functions URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/native-database-functions In PostgreSQL, some [native database functions](/orm/prisma-schema/data-model/unsupported-database-features#native-database-functions) are part of optional extensions. For example, in PostgreSQL versions 12.13 and earlier the `gen_random_uuid()` function is part of the [`pgcrypto`](https://www.postgresql.org/docs/10/pgcrypto.html) extension. To use a PostgreSQL extension, you must install it on the file system of your database server and then activate the extension. If you use Prisma Migrate, this must be done as part of a migration. Do not activate extensions outside a migration file if you use Prisma Migrate. The [shadow database](/orm/prisma-migrate/understanding-prisma-migrate/shadow-database) requires the same extensions. Prisma Migrate creates and deletes the shadow database automatically, so the only way to activate an extension is to include it in a migration file. In Prisma ORM versions 4.5.0 and later, you can activate the extension by declaring it in your Prisma schema with the [`postgresqlExtensions` preview feature](/orm/prisma-schema/postgresql-extensions): ```prisma file=schema.prisma highlight=3,9;add showLineNumbers generator client { provider = "prisma-client-js" //add-next-line previewFeatures = ["postgresqlExtensions"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") //add-next-line extensions = [pgcrypto] } ``` You can then apply these changes to your database with Prisma Migrate. See [How to migrate PostgreSQL extensions](/orm/prisma-schema/postgresql-extensions#how-to-migrate-postgresql-extensions) for details. In earlier versions of Prisma ORM, you must instead add a SQL command to your migration file to activate the extension. See [How to install a PostgreSQL extension as part of a migration](#how-to-install-a-postgresql-extension-as-part-of-a-migration). ## How to install a PostgreSQL extension as part of a migration This section describes how to add a SQL command to a migration file to activate a PostgreSQL extension. If you manage PostgreSQL extensions in your Prisma Schema with the `postgresqlExtensions` preview feature instead, see [How to migrate PostgreSQL extensions](/orm/prisma-schema/postgresql-extensions#how-to-migrate-postgresql-extensions). The following example demonstrates how to install the `pgcrypto` extension as part of a migration: 1. Add the field with the native database function to your schema: ```prisma model User { id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid } ``` If you include a cast operator (such as `::TEXT`), you must surround the entire function with parentheses: ```prisma @default(dbgenerated("(gen_random_uuid()::TEXT)")) ``` 1. Use the `--create-only` flag to generate a new migration without applying it: ```terminal npx prisma migrate dev --create-only ``` 1. Open the generated `migration.sql` file and enable the `pgcrypto` module: ```sql CREATE EXTENSION IF NOT EXISTS pgcrypto; ADD COLUMN "id" UUID NOT NULL DEFAULT gen_random_uuid(), ADD PRIMARY KEY ("id"); ``` 1. Apply the migration: ```terminal npx prisma migrate dev ``` Each time you reset the database or add a new member to your team, all required functions are part of the migration history. --- # Prototyping your schema URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/prototyping-your-schema The Prisma CLI has a dedicated command for prototyping schemas: [`db push`](/orm/reference/prisma-cli-reference#db-push) `db push` uses the same engine as Prisma Migrate to synchronize your Prisma schema with your database schema. The `db push` command: 1. Introspects the database to infer and executes the changes required to make your database schema reflect the state of your Prisma schema. 2. By default, after changes have been applied to the database schema, generators are triggered (for example, Prisma Client). You do not need to manually invoke `prisma generate`. 3. If `db push` anticipates that the changes could result in data loss, it will: - Throw an error - Require the `--accept-data-loss` option if you still want to make the changes > **Notes**: > > - `db push` does not interact with or rely on migrations. The migrations table `_prisma_migrations` will not be created or updated, and no migration files will be generated. > - When working with PlanetScale, we recommend that you use `db push` instead of `migrate`. For details refer to our Getting Started documentation, either [Start from scratch](/getting-started/setup-prisma/start-from-scratch/relational-databases-typescript-planetscale) or [Add to existing project](/getting-started/setup-prisma/add-to-existing-project/relational-databases-typescript-planetscale) depending on your situation. ## Choosing `db push` or Prisma Migrate `db push` works well if: - You want to **quickly prototype and iterate** on schema design locally without the need to deploy these changes to other environments such as other developers, or staging and production environments. - You are prioritizing reaching a **desired end-state** and not the changes or steps executed to reach that end-state (there is no way to preview changes made by `db push`) - You do not need to control how schema changes impact data. There is no way to orchestrate schema and data migrations—if `db push` anticipates that changes will result in data loss, you can either accept data loss with the `--accept-data-loss` option or stop the process. There is no way to customize the changes. See [Schema prototyping with `db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) for an example of how to use `db push` in this way. `db push` is **not recommended** if: - You want to replicate your schema changes in other environments without losing data. You can use `db push` for prototyping, but you should use migrations to commit the schema changes and apply these in your other environments. - You want fine-grained control over how the schema changes are executed - for example, [renaming a column instead of dropping it and creating a new one](/orm/prisma-migrate/workflows/customizing-migrations#example-rename-a-field). - You want to keep track of changes made to the database schema over time. `db push` does not create any artifacts that allow you to keep track of these changes. - You want the schema changes to be reversible. You can use `db push` again to revert to the original state, but this might result in data loss. ## Can I use Prisma Migrate and `db push` together? Yes, you can [use `db push` and Prisma Migrate together in your development workflow](/orm/prisma-migrate/workflows/prototyping-your-schema) . For example, you can: - Use `db push` to prototype a schema at the start of a project and initialize a migration history when you are happy with the first draft - Use `db push` to prototype a change to an existing schema, then run `prisma migrate dev` to generate a migration from your changes (you will be asked to reset) ## Prototyping a new schema The following scenario demonstrates how to use `db push` to synchronize a new schema with an empty database, and evolve that schema - including what happens when `db push` detects that a change will result in data loss. 1. Create a first draft of your schema: ```prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) name String jobTitle String posts Post[] profile Profile? } model Profile { id Int @id @default(autoincrement()) biograpy String // Intentional typo! userId Int @unique user User @relation(fields: [userId], references: [id]) } model Post { id Int @id @default(autoincrement()) title String published Boolean @default(true) content String @db.VarChar(500) authorId Int author User @relation(fields: [authorId], references: [id]) categories Category[] } model Category { id Int @id @default(autoincrement()) name String @db.VarChar(50) posts Post[] @@unique([name]) } ``` 2. Use `db push` to push the initial schema to the database: ```terminal npx prisma db push ``` 3. Create some example content: ```ts const add = await prisma.user.create({ data: { name: 'Eloise', jobTitle: 'Programmer', posts: { create: { title: 'How to create a MySQL database', content: 'Some content', }, }, }, }) ``` 4. Make an additive change - for example, create a new required field: ```prisma highlight=6;add // ... // model Post { id Int @id @default(autoincrement()) title String //add-next-line description String published Boolean @default(true) content String @db.VarChar(500) authorId Int author User @relation(fields: [authorId], references: [id]) categories Category[] } // ... // ``` 5. Push the changes: ```terminal npx prisma db push ``` `db push` will fail because you cannot add a required field to a table with existing content unless you provide a default value. 6. Reset **all data** in your database and re-apply migrations. ```terminal npx prisma migrate reset ``` > **Note**: Unlike Prisma Migrate, `db push` does not generate migrations that you can modify to preserve data, and is therefore best suited for prototyping in a development environment. 7. Continue to evolve your schema until it reaches a relatively stable state. 8. Initialize a migration history: ```terminal npx prisma migrate dev --name initial-state ``` The steps taken to reach the initial prototype are not preserved - `db push` does not generate a history. 9. Push your migration history and Prisma schema to source control (e.g. Git). At this point, the final draft of your prototyping is preserved in a migration and can be pushed to other environments (testing, production, or other members of your team). ## Prototyping with an existing migration history The following scenario demonstrates how to use `db push` to prototype a change to a Prisma schema where a migration history already exists. 1. Check out the latest Prisma schema and migration history: ```prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) name String jobTitle String posts Post[] profile Profile? } model Profile { id Int @id @default(autoincrement()) biograpy String // Intentional typo! userId Int @unique user User @relation(fields: [userId], references: [id]) } model Post { id Int @id @default(autoincrement()) title String published Boolean @default(true) content String @db.VarChar(500) authorId Int author User @relation(fields: [authorId], references: [id]) categories Category[] } model Category { id Int @id @default(autoincrement()) name String @db.VarChar(50) posts Post[] @@unique([name]) } ``` 2. Prototype your new feature, which can involve any number of steps. For example, you might: - Create a `tags String[]` field, then run `db push` - Change the field type to `tags Tag[]` and add a new model named `Tag`, then run `db push` - Change your mind and restore the original `tags String[]` field, then call `db push` - Make a manual change to the `tags` field in the database - for example, adding a constraint After experimenting with several solutions, the final schema change looks like this: ```prisma model Post { id Int @id @default(autoincrement()) title String description String published Boolean @default(true) content String @db.VarChar(500) authorId Int author User @relation(fields: [authorId], references: [id]) categories Category[] tags String[] } ``` 3. To create a migration that adds the new `tags` field, run the `migrate dev` command: ```terminal npx prisma migrate dev --name added-tags ``` Prisma Migrate will prompt you to reset because the changes you made manually and with `db push` while prototyping are not part of the migration history: ```bash √ Drift detected: Your database schema is not in sync with your migration history. We need to reset the PostgreSQL database "prototyping" at "localhost:5432". ``` :::warning This will result in total data loss. ::: ```terminal npx prisma migrate reset ``` 4. Prisma Migrate replays the existing migration history, generates a new migration based on your schema changes, and applies those changes to the database. :::tip When using `migrate dev`, if your schema changes mean that seed scripts will no longer work, you can use the `--skip-seed` flag to ignore seed scripts. ::: At this point, the final result of your prototyping is preserved in a migration, and can be pushed to other environments (testing, production, or other members of your team). --- # Troubleshooting URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/troubleshooting This guide describes how to resolve issues with Prisma Migrate in a development environment, which often involves resetting your database. For production-focused troubleshooting, see: - [Production troubleshooting](/orm/prisma-migrate/workflows/patching-and-hotfixing) - [Patching / hotfixing production databases](/orm/prisma-migrate/workflows/patching-and-hotfixing) This guide **does not apply for MongoDB**.
Instead of `migrate dev`, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb).
## Handling migration history conflicts A migration history conflict occurs when there are discrepancies between the **migrations folder in the file system** and the **`_prisma_migrations` table in the database**. #### Causes of migration history conflict in a development environment - A migration that has already been applied is later modified - A migration that has already been applied is missing from the file system In a development environment, switching between feature branches can result in a history conflict because the `_prisma_migrations` table contains migrations from `branch-1`, and switching to `branch-2` might cause some of those migrations to disappear. > **Note**: You should [never purposefully delete or edit a migration](/orm/prisma-migrate/understanding-prisma-migrate/migration-histories#do-not-edit-or-delete-migrations-that-have-been-applied), as this might result in discrepancies between development and production. #### Fixing a migration history conflict in a development environment If Prisma Migrate detects a migration history conflict when you run `prisma migrate dev`, the CLI will ask to reset the database and reapply the migration history. ## Schema drift Database schema drift occurs when your database schema is out of sync with your migration history - the database schema has 'drifted away' from the source of truth. #### Causes of schema drift in a development environment Schema drift can occur if: - The database schema was changed _without_ using migrations - for example, by using [`prisma db push`](/orm/reference/prisma-cli-reference#db-push) or manually changing the database schema. > **Note**: The [shadow database](/orm/prisma-migrate/understanding-prisma-migrate/shadow-database) is required to detect schema drift, and can therefore only be done in a development environment. #### Fixing schema drift in a development environment If you made manual changes to the database that you do not want to keep, or can easily replicate in the Prisma schema: 1. Reset your database: ```terminal npx prisma migrate reset ``` 1. Replicate the changes in the Prisma schema and generate a new migration: ```terminal npx prisma migrate dev ``` If you made manual changes to the database that you want to keep, you can: 1. Introspect the database: ```terminal npx prisma db pull ``` Prisma will update your schema with the changes made directly in the database. 1. Generate a new migration to include the introspected changes in your migration history: ```terminal npx prisma migrate dev --name introspected_change ``` Prisma Migrate will prompt you to reset, then applies all existing migrations and a new migration based on the introspected changes. Your database and migration history are now in sync, including your manual changes. ## Failed migrations #### Causes of failed migrations in a development environment A migration might fail if: - You [modify a migration before running it](/orm/prisma-migrate/workflows/customizing-migrations) and introduce a syntax error - You add a mandatory (`NOT NULL`) column to a table that already has data - The migration process stopped unexpectedly - The database shut down in the middle of the migration process Each migration in the `_prisma_migrations` table has a `logs` column that stores the error. #### Fixing failed migrations in a development environment The easiest way to handle a failed migration in a developer environment is to address the root cause and reset the database. For example: - If you introduced a SQL syntax error by manually editing the database, update the `migration.sql` file that failed and reset the database: ```terminal prisma migrate reset ``` - If you introduced a change in the Prisma schema that cannot be applied to a database with data (for example, a mandatory column in a table with data): 1. Delete the `migration.sql` file. 2. Modify the schema - for example, add a default value to the mandatory field. 3. Migrate: ```terminal prisma migrate dev ``` Prisma Migrate will prompt you to reset the database and re-apply all migrations. - If something interrupted the migration process, reset the database: ```terminal prisma migrate reset ``` ## Prisma Migrate and PgBouncer You might see the following error if you attempt to run Prisma Migrate commands in an environment that uses PgBouncer for connection pooling: ```bash Error: undefined: Database error Error querying the database: db error: ERROR: prepared statement "s0" already exists ``` See [Prisma Migrate and PgBouncer workaround](/orm/prisma-client/setup-and-configuration/databases-connections/pgbouncer) for further information and a workaround. --- # Baselining a database URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/baselining Baselining is the process of initializing a migration history for a database that: - ✔ Existed before you started using Prisma Migrate - ✔ Contains data that must be maintained (like production), which means that the database cannot be reset Baselining tells Prisma Migrate to assume that one or more migrations have **already been applied**. This prevents generated migrations from failing when they try to create tables and fields that already exist. > **Note**: We assume it is acceptable to reset and seed development databases. Baselining is part of [adding Prisma Migrate to a project with an existing database](/orm/prisma-migrate/getting-started#adding-prisma-migrate-to-an-existing-project). This guide **does not apply for MongoDB**.
Instead of `migrate deploy`, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb).
## Why you need to baseline When you add Prisma Migrate to an existing project, your initial migration contains all the SQL required to recreate the state of the database **before you started using Prisma Migrate**: ![The image shows a database labelled 'Existing database', and a list of existing database features next to it - 24 tables, 13 relationships, 92 fields, 3 indexes. An arrow labelled 'represented by' connects the database features list to a box that represents a migration. The existing databases's features are represented by a single migration.](./existing-database.png) :::tip You can edit the initial migration to include schema elements that cannot be represented in the Prisma schema - such as stored procedures or triggers. ::: You need this initial migration to create and reset **development environments**: ![The image shows a migration history with three migrations. Each migration is represented by a file icon and a name, and all migrations are surrounded by a box labelled 'migration history'. The first migration has an additional label: "State of database before Prisma Migrate", and the two remaining migrations are labelled "Generated as part of the Prisma Migrate workflow". An arrow labelled "prisma migrate dev" connects the migration history box to a database labelled "new development database", signifying that all three migrations are applied to the development database - none are skipped.](./new-dev-db.png) However, when you `prisma migrate deploy` your migrations to databases that already exist and _cannot_ be reset - such as production - you **do not want to include the initial migrations**. The target database already contains the tables and columns created by the initial migration, and attempting to create these elements again will most likely result in an error. ![A migration history represented by three migration files (file icon and name), surrounded by a a box labelled 'migration history'. The first migration is marked 'do not apply', and the second two migrations are marked 'apply'. An arrow labelled with the command 'prisma migrate deploy' points from the migration history to a database labelled 'production'.](./deploy-db.png) Baselining solves this problem by telling Prisma Migrate to pretend that the initial migration(s) **have already been applied**. ## Baselining a database To create a baseline migration: 1. If you have a `prisma/migrations` folder, delete, move, rename, or archive this folder. 1. Run the following command to create a `migrations` directory inside with your preferred name. This example will use `0_init` for the migration name: ```terminal mkdir -p prisma/migrations/0_init ``` :::info Then `0_` is important because Prisma Migrate applies migrations in a [lexicographic order](https://en.wikipedia.org/wiki/Lexicographic_order). You can use a different value such as the current timestamp. ::: 1. Generate a migration and save it to a file using `prisma migrate diff` ```terminal no-lines npx prisma migrate diff \ --from-empty \ --to-schema-datamodel prisma/schema.prisma \ --script > prisma/migrations/0_init/migration.sql ``` 1. Run the `prisma migrate resolve` command for each migration that should be ignored: ```terminal wrap npx prisma migrate resolve --applied 0_init ``` This command adds the target migration to the `_prisma_migrations` table and marks it as applied. When you run `prisma migrate deploy` to apply new migrations, Prisma Migrate: 1. Skips all migrations marked as 'applied', including the baseline migration 1. Applies any new migrations that come _after_ the baseline migration --- # Customizing migrations URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/customizing-migrations This guide **does not apply for MongoDB**.
Instead of `migrate dev`, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb).
In some scenarios, you need to edit a migration file before you apply it. For example, to [change the direction of a 1-1 relation](#example-change-the-direction-of-a-1-1-relation) (moving the foreign key from one side to another) without data loss, you need to move data as part of the migration - this SQL is not part of the default migration, and must be written by hand. This guide explains how to edit migration files and gives some examples of use cases where you may want to do this.
## How to edit a migration file To edit a migration file before applying it, the general procedure is the following: 1. Make a schema change that requires custom SQL (for example, to preserve existing data) 1. Create a draft migration using: ```terminal npx prisma migrate dev --create-only ``` 1. Modify the generated SQL file. 1. Apply the modified SQL by running: ```terminal npx prisma migrate dev ``` ### Example: Rename a field By default, renaming a field in the schema results in a migration that will: - `CREATE` a new column (for example, `fullname`) - `DROP` the existing column (for example, `name`) and the data in that column To actually **rename** a field and avoid data loss when you run the migration in production, you need to modify the generated migration SQL before applying it to the database. Consider the following schema fragment - the `biograpy` field is spelled wrong. ```prisma highlight=3;normal; model Profile { id Int @id @default(autoincrement()) //highlight-next-line biograpy String userId Int @unique user User @relation(fields: [userId], references: [id]) } ``` To rename the `biograpy` field to `biography`: 1. Rename the field in the schema: ```prisma highlight=3;delete|4;add; model Profile { id Int @id @default(autoincrement()) //delete-next-line biograpy String //add-next-line biography String userId Int @unique user User @relation(fields: [userId], references: [id]) } ``` 1. Run the following command to create a **draft migration** that you can edit before applying to the database: ```terminal npx prisma migrate dev --name rename-migration --create-only ``` 1. Edit the draft migration as shown, changing `DROP` / `DELETE` to a single `RENAME COLUMN`: ```sql file=./prisma/migrations/20210308092620_rename_migration/migration.sql ALTER TABLE "Profile" DROP COLUMN "biograpy", ADD COLUMN "biography" TEXT NOT NULL; ``` ```sql file=./prisma/migrations/20210308092620_rename_migration/migration.sql ALTER TABLE "Profile" RENAME COLUMN "biograpy" TO "biography" ``` For SQL Server, you should use the stored procedure `sp_rename` instead of `ALTER TABLE RENAME COLUMN`. ```sql file=./prisma/migrations/20210308092620_rename_migration/migration.sql EXEC sp_rename 'dbo.Profile.biograpy', 'biography', 'COLUMN'; ``` 1. Save and apply the migration: ```terminal npx prisma migrate dev ``` You can use the same technique to rename a `model` - edit the generated SQL to _rename_ the table rather than drop and re-create it. ### Example: Use the expand and contract pattern to evolve the schema without downtime Making schema changes to existing fields, e.g., renaming a field can lead to downtime. It happens in the time frame between applying a migration that modifies an existing field, and deploying a new version of the application code which uses the modified field. You can prevent downtime by breaking down the steps required to alter a field into a series of discrete steps designed to introduce the change gradually. This pattern is known as the _expand and contract pattern_. The pattern involves two components: your application code accessing the database and the database schema you intend to alter. With the _expand and contract_ pattern, renaming the field `bio` to `biography` would look as follows with Prisma: 1. Add the new `biography` field to your Prisma schema and create a migration ```prisma highlight=4;add; model Profile { id Int @id @default(autoincrement()) bio String //add-next-line biography String userId Int @unique user User @relation(fields: [userId], references: [id]) } ``` 2. _Expand_: update the application code and write to both the `bio` and `biography` fields, but continue reading from the `bio` field, and deploy the code 3. Create an empty migration and copy existing data from the `bio` to the `biography` field ```terminal npx prisma migrate dev --name copy_biography --create-only ``` ```sql file=prisma/migrations/20210420000000_copy_biography/migration.sql UPDATE "Profile" SET biography = bio; ``` 4. Verify the integrity of the `biography` field in the database 5. Update application code to **read** from the new `biography` field 6. Update application code to **stop writing** to the `bio` field 7. _Contract_: remove the `bio` from the Prisma schema, and create a migration to remove the `bio` field ```prisma highlight=3;delete; model Profile { id Int @id @default(autoincrement()) //delete-next-line bio String biography String userId Int @unique user User @relation(fields: [userId], references: [id]) } ``` ```terminal npx prisma migrate dev --name remove_bio ``` By using this approach, you avoid potential downtime that altering existing fields that are used in the application code are prone to, and reduce the amount of coordination required between applying the migration and deploying the updated application code. Note that this pattern is applicable in any situation involving a change to a column that has data and is in use by the application code. Examples include combining two fields into one, or transforming a `1:n` relation to a `m:n` relation. To learn more, check out the Data Guide article on [the expand and contract pattern](https://www.prisma.io/dataguide/types/relational/expand-and-contract-pattern) ### Example: Change the direction of a 1-1 relation To change the direction of a 1-1 relation: 1. Make the change in the schema: ```prisma model User { id Int @id @default(autoincrement()) name String posts Post[] profile Profile? @relation(fields: [profileId], references: [id]) profileId Int @unique } model Profile { id Int @id @default(autoincrement()) biography String user User } ``` 1. Run the following command to create a **draft migration** that you can edit before applying to the database: ```terminal npx prisma migrate dev --name rename-migration --create-only ``` ```code no-copy ⚠️ There will be data loss when applying the migration: • The migration will add a unique constraint covering the columns `[profileId]` on the table `User`. If there are existing duplicate values, the migration will fail. ``` 1. Edit the draft migration as shown: ```sql -- DropForeignKey ALTER TABLE "Profile" DROP CONSTRAINT "Profile_userId_fkey"; -- DropIndex DROP INDEX "Profile_userId_unique"; -- AlterTable ALTER TABLE "Profile" DROP COLUMN "userId"; -- AlterTable ALTER TABLE "User" ADD COLUMN "profileId" INTEGER NOT NULL; -- CreateIndex CREATE UNIQUE INDEX "User_profileId_unique" ON "User"("profileId"); -- AddForeignKey ALTER TABLE "User" ADD FOREIGN KEY ("profileId") REFERENCES "Profile"("id") ON DELETE CASCADE ON UPDATE CASCADE; ``` ```sql -- DropForeignKey ALTER TABLE "Profile" DROP CONSTRAINT "Profile_userId_fkey"; -- DropIndex DROP INDEX "Profile_userId_unique"; -- AlterTable ALTER TABLE "User" ADD COLUMN "profileId" INTEGER; UPDATE "User" SET "profileId" = "Profile".id FROM "Profile" WHERE "User".id = "Profile"."userId"; ALTER TABLE "User" ALTER COLUMN "profileId" SET NOT NULL; -- AlterTable ALTER TABLE "Profile" DROP COLUMN "userId"; -- CreateIndex CREATE UNIQUE INDEX "User_profileId_unique" ON "User"("profileId"); -- AddForeignKey ALTER TABLE "User" ADD FOREIGN KEY ("profileId") REFERENCES "Profile"("id") ON DELETE CASCADE ON UPDATE CASCADE; ``` 1. Save and apply the migration: ```terminal npx prisma migrate dev ``` --- # Data migrations URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/data-migration This guide has been moved to our new [guides section](/guides/data-migration). You can find the guide there. --- # Squashing migrations URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/squashing-migrations This guide describes how to squash multiple [migration files](/orm/prisma-migrate/understanding-prisma-migrate/migration-histories) into a single migration. ## About squashing migrations It is sometimes useful to squash either some or all migration files into a single migration. This guide will describe two scenarios where you may want to do this: - [Migrating cleanly from a development environment](#migrating-cleanly-from-a-development-environment) by squashing your local migrations into one before merging - [Creating a clean history in a production environment](#creating-a-clean-history-in-a-production-environment) by squashing all migrations into a single file In both cases, Prisma Migrate provides the tools for doing this, by using the [`migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) command to compare two database schemas and output a single SQL file that takes you from one to the other. The rest of this guide gives detailed instructions on how to carry this out in these two scenarios. ### Migrating cleanly from a development environment Squashing migrations can be useful when developing with a branch-based workflow. During a large local development effort on a feature branch you might generate multiple migrations using `migrate dev`. After the feature is finished, the migration history might contain unnecessary intermediate steps that are unwanted in the final migration history that will be pushed to the `main` branch. There could be important reasons to avoid applying the intermediate steps in production — they might lose data or be extremely slow / disruptive). Even when this is not the case, you may want to avoid clutter in your production environment's migrations history. For detailed steps on how to achieve this using `migrate dev`, see the section on [how to migrate cleanly from a development environment](#how-to-migrate-cleanly-from-a-development-environment). ### Creating a clean history in a production environment Squashing migrations can also be used in a production environment to squash all migration files into one. This can be useful when the production environment has accumulated a longer migration history, and replaying it in new environments has become a burden due to intermediate steps requiring extra time. Since the team is not deriving value from the migration steps (and could get them back from version control history in a pinch) the decision is made to squash the whole history into a single migration. For detailed steps on how to achieve this using `migrate diff` and `migrate resolve` see the section on [how to create a clean history in a production environment](#how-to-create-a-clean-history-in-a-production-environment). ## Considerations when squashing migrations When squashing migrations, be aware that any manually changed or added SQL in your `migration.sql` files will not be retained. If you have migration files with custom additions such as a view or a trigger, ensure to re-add them after your migrations were squashed. ## How to squash migrations This section provides step-by-step instructions on how to squash migrations in the two scenarios discussed above: - [Migrating cleanly from a development environment](#how-to-migrate-cleanly-from-a-development-environment) - [Creating a clean history in a production environment](#how-to-create-a-clean-history-in-a-production-environment) ### How to migrate cleanly from a development environment Before squashing your migrations, make sure you have the following starting conditions: - The contents of the migrations to be squashed are not yet applied on the production database - All migrations applied to production are part of the local migration history already - There is no custom SQL in any of the new migration files that you have added to your branch If the migration history on the production database has diverged after you created your feature branch, then you would need to first merge the migrations history and the datamodel changes from production into your local history. Then follow these steps: 1. Reset the contents of your local `./prisma/migrations` folder to match the migration history on the `main` branch 2. Create a new migration: ```terminal npx prisma migrate dev --name squashed_migrations ``` This creates a single migration that takes you: - from the state of the `main` branch as described in your reset migration history - to the state of your local feature as described in your `./prisma/schema.prisma` file - and outputs this to a new `migration.sql` file in a new directory ending with `squashed_migrations` (specified with the `--name` flag) This single migration file can now be applied to production using `migrate deploy`. ### How to create a clean history in a production environment Before squashing your migrations, make sure you have the following starting conditions: - All migrations in the migration history are applied on the production database - The datamodel matches the migration history - The datamodel and the migration history are in sync Then follow these steps, either on your `main` branch or on a newly checked out branch that gets merged back to `main` before anything else changes there: 1. Delete all contents of the `./prisma/migrations` directory 2. Create a new empty directory in the `./prisma/migrations` directory. In this guide this will be called `000000000000_squashed_migrations`. Inside this, add a new empty `migration.sql` file. We name the migration `000000000000_squashed_migrations` with all the leading zeroes because we want it to be the first migration in the migrations directory. Migrate runs the migrations in the directory in lexicographic (alphabetical) order. This is why it generates migrations with the date and time as a prefix when you use `migrate dev`. You can give the migration another name, as long as it it sorts lower than later migrations, for example `0_squashed` or `202207180000_squashed`. 3. Create a single migration that takes you: - from an empty database - to the current state of the production database schema as described in your `./prisma/schema.prisma` file - and outputs this to the `migration.sql` file created above You can do this using the `migrate diff` command. From the root directory of your project, run the following command: ```terminal npx prisma migrate diff \ --from-empty \ --to-schema-datamodel ./prisma/schema.prisma \ --script > ./prisma/migrations/000000000000_squashed_migrations/migration.sql ``` 4. Mark this migration as having been applied on production, to prevent it from being run there: You can do this using the [`migrate resolve`](/orm/reference/prisma-cli-reference#migrate-resolve) command to mark the migration in the `000000000000_squashed_migrations` directory as already applied: ```terminal npx prisma migrate resolve \ --applied 000000000000_squashed_migrations ``` You should now have a single migration file that is marked as having been applied on production. New checkouts only get one single migration taking them to the state of the production database schema. The production database still contains the history of applied migrations in the migrations table. The history of the migrations folder and data models is also still available in source control. --- # Generating down migrations URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/generating-down-migrations This guide describes how to generate a down migration SQL file that reverses a given [migration file](/orm/prisma-migrate/understanding-prisma-migrate/migration-histories). ## About down migrations When generating a migration SQL file, you may wish to also create a "down migration" SQL file that reverses the schema changes in the corresponding "up migration" file. Note that "down migrations" are also sometimes called "migration rollbacks". This guide explains how to use Prisma Migrate's [`migrate diff` command](/orm/reference/prisma-cli-reference#migrate-diff) to create a down migration, and how to apply it to your production database with the [`db execute`](/orm/reference/prisma-cli-reference#db-execute) command in the case of a failed up migration. This guide applies to generating SQL down migrations for relational databases only. It does not apply to MongoDB. The `migrate diff` and `db execute` commands are available in Preview in versions `3.9.0` and later, and are generally available in versions `3.13.0` and later. ## Considerations when generating down migrations When generating a down migration file, there are some considerations to be aware of: - The down migration can be used to revert your database schema after a failed migration using the steps in [How to apply your down migration to a failed migration](#how-to-apply-your-down-migration-to-a-failed-migration). This requires the use of the `migrate resolve` command, which can only be used on failed migrations. If your up migration was successful and you want to revert it, you will instead need to revert your `schema.prisma` file to its state before the up migration, and generate a new migration with the `migrate dev` command. - The down migration will revert your database schema, but other changes to data and application code that are carried out as part of the up migration will not be reverted. For example, if you have a script that changes data during the migration, this data will not be changed back when you run the down migration. - You will not be able to use `migrate diff` to revert manually changed or added SQL in your migration files. If you have any custom additions, such as a view or trigger, you will need to: - Create the down migration following [the instructions below](#how-to-generate-and-run-down-migrations) - Create the up migration using [`migrate dev --create-only`](/orm/reference/prisma-cli-reference#options-6), so that it can be edited before it is applied to the database - Manually add your custom SQL to the up migration (e.g. adding a view) - Manually add the inverted custom SQL to the down migration (e.g. dropping the view) ## How to generate and run down migrations This section describes how to generate a down migration SQL file along with the corresponding up migration, and then run it to revert your database schema after a failed up migration on production. As an example, take the following Prisma schema with a `User` and `Post` model as a starting point: ```prisma file=schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) content String? author User @relation(fields: [authorId], references: [id]) authorId Int } model User { id Int @id @default(autoincrement()) name String? posts Post[] } ``` You will need to create the down migration first, before creating the corresponding up migration. ### Generating the migrations 1. Edit your Prisma schema to make the changes you require for your up migration. In this example, you will add a new `Profile` model: ```prisma file=schema.prisma highlight=8-14;add|20;add showLineNumbers model Post { id Int @id @default(autoincrement()) title String @db.VarChar(255) content String? author User @relation(fields: [authorId], references: [id]) authorId Int } //add-start model Profile { id Int @id @default(autoincrement()) bio String? user User @relation(fields: [userId], references: [id]) userId Int @unique } //add-end model User { id Int @id @default(autoincrement()) name String? posts Post[] //add-next-line profile Profile? } ``` 2. Generate the SQL file for the down migration. To do this, you will use `migrate diff` to make a comparison: - from the newly edited schema - to the state of the schema after the last migration and output this to a SQL script, `down.sql`. There are two potential options for specifying the 'to' state: - Using `--to-migrations`: this makes a comparison to the state of the migrations given in the migrations directory. This is the preferred option, as it is more robust, but it requires a [shadow database](/orm/prisma-migrate/understanding-prisma-migrate/shadow-database). To use this option, run: ```terminal wrap npx prisma migrate diff \ --from-schema-datamodel prisma/schema.prisma \ --to-migrations prisma/migrations \ --shadow-database-url $SHADOW_DATABASE_URL \ --script > down.sql ``` - Using `--to-schema-datasource`: this makes a comparison to the state of the database. This does not require a shadow database, but it does rely on the database having an up-to-date schema. To use this option, run: ```terminal wrap npx prisma migrate diff \ --from-schema-datamodel prisma/schema.prisma \ --to-schema-datasource prisma/schema.prisma \ --script > down.sql ``` 3. Generate and apply the up migration with a name of `add_profile`: ```terminal npx prisma migrate dev --name add_profile ``` This will create a new `_add_profile` directory inside the `prisma/migrations` directory, with your new `migration.sql` up migration file inside. 4. Copy your `down.sql` file into the new directory along with the up migration file. ### How to apply your down migration to a failed migration If your previous up migration failed, you can apply your down migration on your production database with the following steps: To apply the down migration on your production database after a failed up migration: 1. Use `db execute` to run your `down.sql` file on the database server: ```terminal npx prisma db execute --file ./down.sql --schema prisma/schema.prisma ``` 2. Use `migrate resolve` to record that you rolled back the up migration named `add_profile`: ```terminal npx prisma migrate resolve --rolled-back add_profile ``` --- # Patching & hotfixing URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/patching-and-hotfixing Patching or hotfixing a database involves making an often time critical change directly in production. For example, you might add an index directly to a production database to resolve an issue with a slow-running query. Patching the production database directly results in **schema drift**: your database schema has 'drifted away' from the source of truth, and is out of sync with your migration history. You can use the `prisma migrate resolve` command to reconcile your migration history _without_ having to remove and re-apply the hotfix with `prisma migrate deploy`. This guide **does not apply for MongoDB**.
Instead of `migrate dev`, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb).
## Reconciling your migration history with a patch or hotfix The following scenario assumes that you made a manual change in production and want to propagate that change to your migration history and other databases. To reconcile your migration history and database schema in production: 1. Replicate the change you made in production in the schema - for example, add an `@@index` to a particular model. 1. Generate a new migration and take note of the full migration name, including a timestamp, which is written to the CLI:(`20210316150542_retroactively_add_index`): ```terminal npx prisma migrate dev --name retroactively-add-index ``` ```bash no-copy migrations/ └─ 20210316150542_retroactively_add_index/ └─ migration.sql Your database is now in sync with your schema. ✔ Generated Prisma Client (2.19.0-dev.29) to .\node_modules\@prisma\client in 190ms ``` 1. Push the migration to production **without running `migrate deploy`**. Instead, mark the migration created in the previous step as 'already applied' so that Prisma Migrate does not attempt to apply your hotfix a second time: ```terminal prisma migrate resolve --applied "20201127134938-retroactively-add-index" ``` This command adds the migration to the migration history table without running the actual SQL. 1. Repeat the previous step for other databases that were patched - for example, if you applied the patch to a staging database. 1. Propagate the migration to other databases that were not patched - for example, by committing the migration to source control and allowing your CI/CD pipeline to apply it to all databases. > **Note**: The migration will not be applied to databases where it has been marked as already applied by the `prisma migrate resolve` command. ## Failed migration A migration might fail if: - You [modify a migration before running it](/orm/prisma-migrate/workflows/customizing-migrations) and introduce a syntax error - You add a mandatory (`NOT NULL`) column to a table that already has data - The migration process stopped unexpectedly - The database shut down in the middle of the migration process Each migration in the `_prisma_migrations` table has a `logs` column that stores the error. There are two ways to deal with failed migrations in a production environment: - Roll back, optionally fix issues, and re-deploy - Manually complete the migration steps and resolve the migration ### Option 1: Mark the migration as rolled back and re-deploy The following example demonstrates how to roll back a migration, optionally make changes to fix the issue, and re-deploy: 1. Mark the migration as rolled back - this updates the migration record in the `_prisma_migrations` table to register it as rolled back, allowing it to be applied again: ```terminal prisma migrate resolve --rolled-back "20201127134938_added_bio_index" ``` 1. If the migration was partially run, you can either: - Modify the migration to check if a step was already completed (for example: `CREATE TABLE ... IF NOT EXISTS`) _OR_ - Manually revert the steps that were completed (for example, delete created tables) > If you modify the migration, make sure you copy it back to source control to ensure that state of your production database is reflected exactly in development. 1. Fix the root cause of the failed migration, if relevant - for example, if the migration failed due to an issue with the SQL script itself. Make sure that you copy any changed migrations back to source control. 1. Re-deploy the migration: ```terminal prisma migrate deploy ``` ### Option 2: Manually complete migration and resolve as applied The following example demonstrates how to manually complete the steps of a migration and mark that migration as applied. 1. Manually complete the migration steps on the production database. Make sure that any manual steps exactly match the steps in the migration file, and copy any changes back to source control. 1. Resolve the migration as applied - this tells Prisma Migrate to consider the migration successfully applied: ```terminal prisma migrate resolve --applied "20201127134938_my_migration" ``` ## Fixing failed migrations with `migrate diff` and `db execute` To help with fixing a failed migration, Prisma ORM provides the following commands for creating and executing a migration file: - [`prisma migrate diff`](/orm/reference/prisma-cli-reference#migrate-diff) which diffs two database schema sources to create a migration taking one to the state of the second. You can output either a summary of the difference or a sql script. The script can be output into a file via `> file_name.sql` or be piped to the `db execute --stdin` command. - [`prisma db execute`](/orm/reference/prisma-cli-reference#db-execute) which applies a SQL script to the database without interacting with the Prisma migrations table. These commands are available in Preview in versions `3.9.0` and later (with the `--preview-feature` CLI flag), and generally available in versions `3.13.0` and later. This section gives an example scenario of a failed migration, and explains how to use `migrate diff` and `db execute` to fix it. ### Example of a failed migration Imagine that you have the following `User` model in your schema, in both your local development environment and your production environment: ```prisma file=schema.prisma showLineNumbers model User { id Int @id name String } ``` At this point, your schemas are in sync, but the data in the two environments is different. You then decide to make changes to your data model, adding another `Post` model and making the `name` field on `User` unique: ```prisma file=schema.prisma showLineNumbers model User { id Int @id name String @unique email String? } model Post { id Int @id title String } ``` You create a migration called 'Unique' with the command `prisma migrate dev -n Unique` which is saved in your local migrations history. Applying the migration succeeds in your dev environment and now it is time to release to production. Unfortunately this migration can only be partially executed. Creating the `Post` model and adding the `email` column succeeds, but making the `name` field unique fails with the following error: ```bash ERROR 1062 (23000): Duplicate entry 'paul' for key 'User_name_key' ``` This is because there is non-unique data in your production database (e.g. two users with the same name). You now need to recover manually from the partially executed migration. Until you recover from the failed state, further migrations using `prisma migrate deploy` are impossible. At this point there are two options, depending on what you decide to do with the non-unique data: - You realize that non-unique data is valid and you cannot move forward with your current development work. You want to roll back the complete migration. To do this, see [Moving backwards and reverting all changes](#moving-backwards-and-reverting-all-changes) - The existence of non-unique data in your database is unintentional and you want to fix that. After fixing, you want to go ahead with the rest of the migration. To do this, see [Moving forwards and applying missing changes](#moving-forwards-and-applying-missing-changes) #### Moving backwards and reverting all changes In this case, you need to create a migration that takes your production database to the state of your data model before the last migration. - First you need your migration history at the time before the failed migration. You can either get this from your git history, or locally delete the folder of the last failed migration in your migration history. - You now want to take your production environment from its current failed state back to the state specified in your local migrations history: - Run the following `prisma migrate diff` command: ```terminal wrap npx prisma migrate diff \ --from-url "$DATABASE_URL_PROD" \ --to-migrations ./prisma/migrations \ --shadow-database-url $SHADOW_DATABASE_URL \ --script > backward.sql ``` This will create a SQL script file containing all changes necessary to take your production environment from its current failed state to the target state defined by your migrations history. Note that because we're using `--to-migrations`, the command requires a [shadow database](/orm/prisma-migrate/understanding-prisma-migrate/shadow-database). - Run the following `prisma db execute` command: ```bash npx prisma db execute --url "$DATABASE_URL_PROD" --file backward.sql ``` This applies the changes in the SQL script against the target database without interacting with the migrations table. - Run the following `prisma migrate resolve` command: ```bash npx prisma migrate resolve --rolled-back Unique ``` This will mark the failed migration called 'Unique' in the migrations table on your production environment as rolled back. Your local migration history now yields the same result as the state your production database is in. You can now modify the datamodel again to create a migration that suits your new understanding of the feature you're working on (with non-unique names). #### Moving forwards and applying missing changes In this case, you need to fix the non-unique data and then go ahead with the rest of the migration as planned: - The error message from trying to deploy the migration to production already told you there was duplicate data in the column `name`. You need to either alter or delete the offending rows. - Continue applying the rest of the failed migration to get to the data model defined in your `schema.prisma` file: - Run the following `prisma migrate diff` command: ```bash npx prisma migrate diff --from-url "$DATABASE_URL_PROD" --to-schema-datamodel schema.prisma --script > forward.sql ``` This will create a SQL script file containing all changes necessary to take your production environment from its current failed state to the target state defined in your `schema.prisma` file. - Run the following `prisma db execute` command: ```bash npx prisma db execute --url "$DATABASE_URL_PROD" --file forward.sql ``` This applies the changes in the SQL script against the target database without interacting with the migrations table. - Run the following `prisma migrate resolve` command: ```bash npx prisma migrate resolve --applied Unique ``` This will mark the failed migration called 'Unique' in the migrations table on your production environment as applied. Your local migration history now yields the same result as the state your production environment is in. You can now continue using the already known `migrate dev` /`migrate deploy` workflow. ## Migration history conflicts This does not apply from version [3.12.0](https://github.com/prisma/prisma/releases/tag/3.12.0) upwards. `prisma migrate deploy` issues a warning if an already applied migration has been edited - however, it does not stop the migration process. To remove the warnings, restore the original migration from source control. ## Prisma Migrate and PgBouncer You might see the following error if you attempt to run Prisma Migrate commands in an environment that uses PgBouncer for connection pooling: ```bash Error: undefined: Database error Error querying the database: db error: ERROR: prepared statement "s0" already exists ``` See [Prisma Migrate and PgBouncer workaround](/orm/prisma-client/setup-and-configuration/databases-connections/pgbouncer) for further information and a workaround. Follow [GitHub issue #6485](https://github.com/prisma/prisma/issues/6485) for updates. --- # Unsupported database features URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/unsupported-database-features Prisma Migrate uses the Prisma schema to determine what features to create in the database. However, some database features [cannot be represented in the Prisma schema](/orm/prisma-schema/data-model/unsupported-database-features) , including but not limited to: - Stored procedures - Triggers - Views - Partial indexes To add an unsupported feature to your database, you must [customize a migration](/orm/prisma-migrate/workflows/customizing-migrations) to include that feature before you apply it. :::tip The Prisma schema is able to represent [unsupported field types](/orm/prisma-schema/data-model/unsupported-database-features#unsupported-field-types) and [native database functions](/orm/prisma-migrate/workflows/native-database-functions). ::: This guide **does not apply for MongoDB**.
Instead of `migrate dev`, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb).
## Customize a migration to include an unsupported feature To customize a migration to include an unsupported feature: 1. Use the `--create-only` flag to generate a new migration without applying it: ```terminal npx prisma migrate dev --create-only ``` 1. Open the generated `migration.sql` file and add the unsupported feature - for example, a partial index: ```sql CREATE UNIQUE INDEX tests_success_constraint ON posts (subject, target) WHERE success; ``` 1. Apply the migration: ```terminal npx prisma migrate dev ``` 1. Commit the modified migration to source control. --- # Development and production URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/development-and-production This page explains how to use Prisma Migrate commands in development and production environments. ## Development environments In a development environment, use the `migrate dev` command to generate and apply migrations: ```terminal npx prisma migrate dev ``` ### Create and apply migrations `migrate dev` is a development command and should never be used in a production environment. This command: 1. Reruns the existing migration history in the [shadow database](/orm/prisma-migrate/understanding-prisma-migrate/shadow-database) in order to detect schema drift (edited or deleted migration file, or a manual changes to the database schema) 1. Applies pending migrations to the shadow database (for example, new migrations created by colleagues) 1. If it detects changes to the Prisma schema, it generates a new migration from these changes 1. Applies all unapplied migrations to the development database and updates the `_prisma_migrations` table 1. Triggers the generation of artifacts (for example, Prisma Client) The `migrate dev` command will prompt you to reset the database in the following scenarios: - Migration history conflicts caused by [modified or missing migrations](/orm/prisma-migrate/understanding-prisma-migrate/migration-histories#do-not-edit-or-delete-migrations-that-have-been-applied) - The database schema has drifted away from the end-state of the migration history ### Reset the development database You can also `reset` the database yourself to undo manual changes or `db push` experiments by running: ```terminal npx prisma migrate reset ``` `migrate reset` is a development command and should never be used in a production environment. This command: 1. Drops the database/schema¹ if possible, or performs a soft reset if the environment does not allow deleting databases/schemas¹ 1. Creates a new database/schema¹ with the same name if the database/schema¹ was dropped 1. Applies all migrations 1. Runs seed scripts ¹ For MySQL and MongoDB this refers to the database, for PostgreSQL and SQL Server to the schema, and for SQLite to the database file. > **Note**: For a simple and integrated way to re-create data in your development database as often as needed, check out our [seeding guide](/orm/prisma-migrate/workflows/seeding). ### Customizing migrations Sometimes, you need to modify a migration **before applying it**. For example: - You want to introduce a significant refactor, such as changing blog post tags from a `String[]` to a `Tag[]` - You want to [rename a field](/orm/prisma-migrate/workflows/customizing-migrations#example-rename-a-field) (by default, Prisma Migrate will drop the existing field) - You want to [change the direction of a 1-1 relationship](/orm/prisma-migrate/workflows/customizing-migrations#example-change-the-direction-of-a-1-1-relation) - You want to add features that cannot be represented in Prisma Schema Language - such as a partial index or a stored procedure. The `--create-only` command allows you to create a migration without applying it: ```terminal npx prisma migrate dev --create-only ``` To apply the edited migration, run `prisma migrate dev` again. Refer to [Customizing migrations](/orm/prisma-migrate/workflows/customizing-migrations) for examples. ### Team development See: [Team development with Prisma Migrate](/orm/prisma-migrate/workflows/team-development) . ## Production and testing environments In production and testing environments, use the `migrate deploy` command to apply migrations: ```terminal npx prisma migrate deploy ``` > **Note**: `migrate deploy` should generally be part of an automated CI/CD pipeline, and we do not recommend running this command locally to deploy changes to a production database. This command: 1. Compares applied migrations against the migration history and **warns** if any migrations have been modified: ```bash WARNING The following migrations have been modified since they were applied: 20210313140442_favorite_colors ``` 1. Applies pending migrations The `migrate deploy` command: - **Does not** issue a warning if an already applied migration is _missing_ from migration history - **Does not** detect drift (production database schema differs from migration history end state - for example, due to a hotfix) - **Does not** reset the database or generate artifacts (such as Prisma Client) - **Does not** rely on a shadow database See also: - [Prisma Migrate in deployment](/orm/prisma-client/deployment/deploy-database-changes-with-prisma-migrate) - [Production troubleshooting](/orm/prisma-migrate/workflows/patching-and-hotfixing) ### Advisory locking Prisma Migrate makes use of advisory locking when you run production commands such as: - `prisma migrate deploy` - `prisma migrate dev` - `prisma migrate resolve` This safeguard ensures that multiple commands cannot run at the same time - for example, if you merge two pull requests in quick succession. Advisory locking has a **10 second timeout** (not configurable), and uses the default advisory locking mechanism available in the underlying provider: - [PostgreSQL](https://www.postgresql.org/docs/9.4/explicit-locking.html#ADVISORY-LOCKS) - [MySQL](https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html) - [Microsoft SQL server](https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-getapplock-transact-sql?view=sql-server-ver15) Prisma Migrate's implementation of advisory locking is purely to avoid catastrophic errors - if your command times out, you will need to run it again. Since `5.3.0`, the advisory locking can be disabled using the [`PRISMA_SCHEMA_DISABLE_ADVISORY_LOCK` environment variable](/orm/reference/environment-variables-reference#prisma_schema_disable_advisory_lock) --- # Workflows URL: https://www.prisma.io/docs/orm/prisma-migrate/workflows/index ## In this section --- # Prisma Migrate URL: https://www.prisma.io/docs/orm/prisma-migrate/index ## In this section --- # Prisma CLI URL: https://www.prisma.io/docs/orm/tools/prisma-cli The Prisma command line interface (CLI) is the primary way to interact with your Prisma project from the command line. It can initialize new project assets, generate Prisma Client, and analyze existing database structures through introspection to automatically create your application models. ## Command reference See [Prisma CLI command reference](/orm/reference/prisma-cli-reference) for a complete list of commands. ## Installation The Prisma CLI is typically installed locally as a **development dependency**, that's why the `--save-dev` (npm) and `--dev` (Yarn) options are used in the commands below. ### npm Install with [npm](https://www.npmjs.com/): ``` npm install prisma --save-dev ``` ### Yarn Install with [yarn](https://yarnpkg.com/): ``` yarn add prisma --dev ``` ### pnpm Install with [pnpm](https://pnpm.io/): ``` pnpm install prisma --save-dev ``` ### Bun Install with [Bun](https://bun.sh/): ``` bun add prisma ```
Global installation (Not recommended) :::warning We **do not recommend installing the Prisma CLI globally** because it can lead to version conflicts. ::: - **npm** Install with npm: ``` npm install -g prisma ```
- **Yarn** Install with Yarn: ``` yarn global add prisma ```
- **pnpm** Install with pnpm: ``` pnpm install prisma --global ```
- **Bun** Install with [Bun](https://bun.sh): ``` bun add --global prisma ```
## Usage If you installed Prisma as a development dependency, you need to prefix the `prisma` command with your package runner. ### npm ``` npx prisma ``` ### Yarn ``` yarn prisma ``` ### pnpm ``` pnpm dlx prisma ``` ### Bun ``` bunx prisma ``` ## Synopsis The `prisma` command can be called from command line once installed. When called without arguments, it will display its command usage and help document: ```terminal prisma ``` ```code no-copy Prisma is a modern DB toolkit to query, migrate and model your database (https://www.prisma.io) Usage $ prisma [command] Commands init Setup Prisma for your app generate Generate artifacts (e.g. Prisma Client) db Manage your database schema and lifecycle migrate Migrate your database studio Browse your data with Prisma Studio validate Validate your Prisma schema format Format your Prisma schema Flags --preview-feature Run Preview Prisma commands Examples Setup a new Prisma project $ prisma init Generate artifacts (e.g. Prisma Client) $ prisma generate Browse your data $ prisma studio Create migrations from your Prisma schema, apply them to the database, generate artifacts (e.g. Prisma Client) $ prisma migrate dev Pull the schema from an existing database, updating the Prisma schema $ prisma db pull Push the Prisma schema state to the database $ prisma db push ``` You can get additional help on any of the `prisma` commands by adding the `--help` flag after the command. ## Exit codes All `prisma` CLI commands return the following codes when they exit: - exit code 0 when a command runs successfully - exit code 1 when a command errors - exit code 130 when the CLI receives a signal interrupt (SIGINT) message or if the user cancels a prompt. This exit code is available in Prisma ORM versions 4.3.0 and later. ## Telemetry The term **telemetry** refers to the collection of certain usage data to help _improve the quality of a piece of software_. Prisma uses telemetry in two contexts: - when it collects CLI usage data - when it submits CLI error reports This page describes the overall telemetry approach for Prisma, what kind of data is collected and how to opt-out of data collection. ### Why does Prisma collect metrics? Telemetry helps us better understand _how many users_ are using our products and _how often_ they are using our products. Unlike many telemetry services, our telemetry implementation is intentionally limited in scope and is actually useful for the developer: - **Limited in scope**: We use telemetry to answer one question: how many monthly active developers are using Prisma CLI? - **Provides value**: Our telemetry service also checks for version updates and offers security notices. ### When is data collected? Data is collected in two scenarios that are described below. #### Usage data Invocations of the `prisma` CLI and general usage of Studio results in data being sent to the telemetry server at https://checkpoint.prisma.io. Note that: - The data does **not** include your schema or the data in your database - Prisma only sends information after you execute a CLI command Here is an overview of the data that's being submitted: | Field | Attributes | Description | | -------------: | :--------: | :------------------------------------------------------------------------------------- | | `product` | _string_ | Name of the product (e.g. `prisma`) | | `version` | _string_ | Currently installed version of the product (e.g. `1.0.0-rc0`) | | `arch` | _string_ | Client's operating system architecture (e.g. `amd64`). | | `os` | _string_ | Client's operating system (e.g. `darwin`). | | `node_version` | _string_ | Client's node version (e.g. `v12.12.0`). | | `signature` | _string_ | Random, non-identifiable signature UUID (e.g. `91b014df3-9dda-4a27-a8a7-15474fd899f8`) | | `user_agent` | _string_ | User agent of the checkpoint client (e.g. `prisma/js-checkpoint`) | | `timestamp` | _string_ | When the request was made in RFC3339 format (e.g. `2019-12-12T17:45:56Z`) | You can opt-out of this behavior by setting the `CHECKPOINT_DISABLE` environment variable to `1`, e.g.: ```terminal export CHECKPOINT_DISABLE=1 ``` #### Error reporting Prisma potentially collects error data when there is a crash in the CLI. Before an error report is submitted, there will _always_ be a prompt asking you to confirm or deny the submission of the error report! Error reports are never submitted without your explicit consent! ### How to opt-out of data collection? #### Usage data You can opt-out of usage data collection by setting the `CHECKPOINT_DISABLE` environment variable to `1`, e.g.: ```terminal export CHECKPOINT_DISABLE=1 ``` #### Error reporting You can opt-out of data collection by responding to the interactive prompt with _no_. --- # Prisma Studio URL: https://www.prisma.io/docs/orm/tools/prisma-studio import StudioStringSvg from '/img/studio/string.svg'; import StudioNumberSvg from '/img/studio/number.svg'; import StudioDatetimeSvg from '/img/studio/datetime.svg'; import StudioBooleanSvg from '/img/studio/boolean.svg'; import StudioEnumSvg from '/img/studio/enum.svg'; import StudioArraySvg from '/img/studio/array.svg'; import StudioObjectSvg from '/img/studio/object.svg'; Prisma Studio is a visual editor for the data in your database. Note that Prisma Studio is not open source but you can still create issues in the [`prisma/studio`](https://github.com/prisma/studio) repo. Run `npx prisma studio` in your terminal. ## Models (tables or collections) When you first open Prisma Studio, you will see a data table layout with a sidebar showing a list of all models defined in your Prisma schema file. ![Prisma Studio - Models view](/img/studio/01-models-view.png) :::info **What is a model?**

The term **model** refers to the data model definitions that you add to the Prisma schema file. Depending on the database that you use, a model definition, such as `model User`, refers to a **table** in a relational database (PostgreSQL, MySQL, SQL Server, SQLite, CockroachDB) or a **collection** in MongoDB.

For more information, see [Defining models](/orm/prisma-schema/data-model/models#defining-models). ::: You can select a model and its data opens in a new tab. In this example, the `User` model is selected. ![Prisma Studio - Models view with model open](/img/studio/02-open-model.png) ### Open and close models To open another model, locate the model in the sidebar and click on it. To close a model, click the the **X** button in the model tab. If there are multiple models open, you can also click "Close all" to close all models. ![Prisma Studio - Open and close models](/img/studio/03-open-close-models.png) ### Icons of data types in models The data type for each field is indicated with an icon in the header. The table below lists all data types and their identifying icon. | Field data type | Description | | :-------------------------------------------------------------------------------: | ------------------------------------ | | | Text | | | Integer | | | Date-time

| | | Boolean
| | | Pre-defined list of values (`enum` data type) | | | List of related records from another model | | | The `{}` symbol can refer to one of the two types of fields.

• Relation field
• JSON field | ### Keyboard shortcuts in models When you open a model, a number of keyboard shortcuts are available to browse and manipulate the data in the model. :::info **Note**

With Prisma Studio open, you can open the keyboard shortcuts modal by pressing Cmd ⌘+/ on macOS or Ctrl+/ on Windows. ::: ![Prisma Studio - Keyboard shortcuts](/img/studio/04-model-view-keyboard-shortcuts.png) ## Edit data Prisma Studio offers two mechanisms for editing existing data: [in-line editing](#in-line-editing) and [side panel editing](#side-panel-editing). ### In-line editing To edit data in-line, double-click a cell to enter edit mode. Doing so will place your cursor in the cell and allow you to edit the data. Data can be copied and pasted into cells. All changes (add, edit, or delete) must be confirmed before they will take effect. Confirm added and edited records with the **Save change** button. When you select records and click **Delete records**, confirm the deletion in a dialog box. You can accumulate multiple added records and edited cells, which you can then finalize with the **Save changes** button. ![Prisma Studio - Save inline changes](/img/studio/11-save-inline-changes.png) Once you have finished editing the data, click the green **Save** button. ![Prisma Studio - Save inline changes](/img/studio/11-save-inline-changes.png) ### Batch editing Multiple records can be edited at once. Double click any cell to edit values, moving to any additional cells as necessary. Once complete, click the green **Save** button. ![Prisma Studio - Save multiple inline changes](/img/studio/12-save-multiple-inline-changes.png) ### Side panel editing Prisma Studio also offers a side panel for editing data. To open the side panel, click the **Edit side panel** icon located beside the select checkbox at the far left of every visible record. ![Prisma Studio - Open side panel](/img/studio/13-edit-side-panel-icon.png) Clicking the icon will open the side panel on the right where edits can be performed. Once complete, click outside the side panel and click the green **Save** button to save the changes. ![Prisma Studio - Edit side panel](/img/studio/14-edit-data-in-sidepanel.png) ### Delete records 1. From the left column, select the check box for the records you want to delete. 2. Click **Delete _n_ record(s)**. 3. Click **Delete** in the confirmation dialog. You can select multiple records and delete them at once with the **Delete records** button. When you delete multiple records, the operation completes immediately (after you confirm it). In addition, if you have any accumulated added or edited records and then decide to delete records, the deletion also force-saves the accumulated edits. :::warning **Warning**

Deleting a record is a separate operation that cannot be accumulated. If you delete a record while having unsaved edits, the delete operation first force-saves the unsaved edits and then completes. ::: ![Prisma Studio - Delete records](/img/studio/15-delete-records.png) You can discard any accumulated changes with the **Discard changes** button. ![Prisma Studio - Discard changes](/img/studio/16-discard-changes.png) ### Copy and paste You can copy the value of any table cell using: - Cmd ⌘ + C   on macOS - Ctrl + C     on Windows To paste in another cell, first double-click the cell to enter edit mode, and then use: - Cmd ⌘ + V   on macOS - Ctrl + V     on Windows ### Add a record 1. In the model view, click **Add record**. 2. Based on the data allowed in each field, type the data for the record. | Field data type | Description | | :-------------------------------------------------------------------------------: | ------------------ | | | Text | | | Integer

If such a field has `autoincrement()` pre-filled, do not edit the cell and do not add a number manually. | | | Date-time

Date-time fields contain a long string of numbers, letters, and others. As a best practice, copy the value of another date-time cell and modify it as necessary before pasting in the field. | | | Boolean

Select `true` or `false`. | | | Pre-defined list

Double-click a cell in the field and select one of the pre-defined options. | | | List of related records from another model

It typically refers to a list of records that exist in another model in the database. If you are adding a new record and records from the related model do not yet exist, you do not need to enter anything in the current model. | | | The `{}` symbol can refer to one of the two types of fields.

• Relation field
• JSON field

**Relation with a model defined separately in the database**

Typically, you need to select the same value as any of the previous records
Click the name of the model to see the list of values which you can then select for the related field.

**JSON field**

Double-click the field to edit the JSON data. As a best practice, validate the edited JSON data in a validator and paste it back in the cell. | 3. (Optional) If you are unhappy with your changes, click **Discard changes** and start over. 4. Click **Save 1 change**. ## Filters ### Filter data Use the **Filters** menu to filter data in the model by adding conditions. In the **Filters** menu, the first condition that you add is the `where` clause. When you add multiple conditions, Prisma Studio filters the results so that all conditions apply in combination. Each new condition indicates this with the `and` operator, which appears in front. **Steps** 1. Click **Filters** to open the **Filters** menu. :::info **Note**
Click **Filters** again if you want to hide the menu. ::: 2. Click **Add a new filter**. 3. Configure the condition. 1. Select the field by which you want to filter. 2. Select a comparison operator. - **equals** - **in** - **notin** - **lt** - **lte** - **gt** - **gte** - **not** 3. Type the value you want to use for the condition.
**Step result**: **Prisma Studio** updates the data in the model immediately, based on the condition. 4. To add a new filter, click **Add a new filter** and repeat the steps above. 5. To remove a filter, click the **x** button on the right. ![Prisma Studio - Add and remove filters](/img/studio/06-add-remove-filters.png) 6. To remove all filters, click **Clear all**. **Result** - The data in the model is filtered based on the combination of all conditions you add. - In the **Filters** menu, the default value of **None** changes to display the number of filters you add. ### Show and hide fields You can select which fields to view or hide by using the **Fields** menu. :::info **What is a field?**
A **field** is a property of a model which you add in the data model definitions in the Prisma schema file. Depending on the database that you use, a field, such as the `title` field in `model User { title String }`, refers to a **column** in a relational database (PostgreSQL, MySQL, SQL Server, SQLite, CockroachDB) or a **document field** in MongoDB.
For more information, see [Defining fields](/orm/prisma-schema/data-model/models#defining-fields). ::: **Steps** 1. Click the **Fields** menu. 2. Select only the fields you want to see and deselect any fields you want to hide. ![Prisma Studio - Show and hide fields](/img/studio/07-show-hide-fields.png) **Result** The model is immediately filtered to hide the data from any fields you have deselected. Also, the **Fields** menu shows the number of fields that are currently selected. ### Show and hide records You can also select to show or skip a specific number of records in the model view. :::info **What is a record?**
A **record** refers to a **row of data in a table** in a relational database (PostgreSQL, MySQL, SQL Server, SQLite, CockroachDB) or a **document** in MongoDB. ::: **Steps** 1. Click the **Showing** menu. 2. In the **Take** box, specify the maximum number of records that you want the model view to show. 3. In the **Skip** box, specify how many of the first records you want to hide. ![Prisma Studio - Show and hide records](/img/studio/08-show-hide-records.png) **Result** The model is immediately filtered to show or hide records based on your selection. The **Showing** menu indicates how many records are shown out of how many available records are in the model. ## Sort data Click a field title to sort by the field data. The first click sorts the data in ascending order, the second - in descending order. ![Prisma Studio - Sort data](/img/studio/09-model-sort.png) ## Troubleshooting ### Terminal: Failed to run script / Error in Prisma Client request Caching issues may cause Prisma Studio to use an older version of the query engine. You may see the following error: ```terminal wrap Error in request: PrismaClientKnownRequestError: Failed to validate the query Error occurred during query validation & transformation ``` To resolve, delete the following folders: - `~/.cache/prisma` on macOS and Linux - `%AppData%/Prisma/Studio` on Windows --- # Tools URL: https://www.prisma.io/docs/orm/tools/index ## In this section --- # Prisma Client API reference URL: https://www.prisma.io/docs/orm/reference/prisma-client-reference The Prisma Client API reference documentation is based on the following schema: ```prisma model User { id Int @id @default(autoincrement()) name String? email String @unique profileViews Int @default(0) role Role @default(USER) coinflips Boolean[] posts Post[] city String country String profile ExtendedProfile? pets Json } model ExtendedProfile { id Int @id @default(autoincrement()) userId Int? @unique bio String? User User? @relation(fields: [userId], references: [id]) } model Post { id Int @id @default(autoincrement()) title String published Boolean @default(true) author User @relation(fields: [authorId], references: [id]) authorId Int comments Json views Int @default(0) likes Int @default(0) } enum Role { USER ADMIN } ``` All example generated types (such as `UserSelect` and `UserWhereUniqueInput`) are based on the `User` model. ## `PrismaClient` This section describes the `PrismaClient` constructor and its parameters. ### Remarks - Parameters are validated at runtime. ### `datasources` Programmatically overrides properties of the `datasource` block in the `schema.prisma` file - for example, as part of an integration test. See also: [Data sources](/orm/prisma-schema/overview/data-sources) From version 5.2.0 and upwards, you can also use the [`datasourceUrl`](#datasourceurl) property to programmatically override the database connection string. #### Properties | Example property | Example value | Description | | ---------------- | ----------------------------- | -------------------------------------------------------------- | | `db` | `{ url: 'file:./dev_qa.db' }` | The database [connection URL](/orm/reference/connection-urls). | #### Remarks - You must re-generate Prisma Client each time you add or rename a data source. Datasource names are included in the generated client. - If you named your `datasource` block something else in the schema, replace `db` with the name of your `datasource` block. #### Examples ##### Programmatically override a datasource `url` ```ts import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient({ datasources: { db: { url: 'file:./dev_qa.db', }, }, }); ``` Based on the following `datasource` block: ```prisma datasource db { provider = "sqlite" url = env("DATABASE_URL") } ``` ### `datasourceUrl` Programmatically overrides the [`datasource`](#datasources) block in the `schema.prisma` file. #### Property | Option | Example value | Description | | -------------------------- | -------------------- | -------------------------------------------------------------- | | Database connection string | `'file:./dev_qa.db'` | The database [connection URL](/orm/reference/connection-urls). | #### Examples ```ts import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient({ datasourceUrl: 'postgresql://johndoe:randompassword@localhost:5432/mydb', }); ``` ### `log` Determines the type and level of logging. See also: [Logging](/orm/prisma-client/observability-and-logging/logging) #### Options | Option | Example | | ------------------------ | ------------------------------------------------------------------------ | | Array of log levels | `[ "info", "query" ]` | | Array of log definitions | `[ { level: "info", emit: "event" }, { level: "warn", emit: "stdout" }]` | ##### Log levels | Name | Example | | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `query` | Logs all queries run by Prisma.

For relational databases this logs all SQL queries. Example:
`prisma:query SELECT "public"."User"."id", "public"."User"."email" FROM "public"."User" WHERE ("public"."User"."id") IN (SELECT "t0"."id" FROM "public"."User" AS "t0" INNER JOIN "public"."Post" AS "j0" ON ("j0"."authorId") = ("t0"."id") WHERE ("j0"."views" > $1 AND "t0"."id" IS NOT NULL)) OFFSET $2`

For MongoDB this logs queries using the [`mongosh` shell](https://www.mongodb.com/docs/mongodb-shell/#mongodb-binary-bin.mongosh) format. Example:
`prisma:query db.User.deleteMany({ _id: ( $in: [ “6221ce49f756b0721fc00542”, ], }, })` | | `info` | Example:
`prisma:info Started http server on http://127.0.0.1:58471` | | `warn` | Warnings. | | `error` | Errors. | ##### Emit formats | Name | Description | | -------- | ------------------------------------------------------------- | | `stdout` | See: [stdout](https://en.wikipedia.org/wiki/Standard_streams) | | `event` | Raises an event that you can subscribe to. | ##### Event types The `query` event type: ```ts file=index.d.ts export type QueryEvent = { timestamp: Date; query: string; // Query sent to the database params: string; // Query parameters duration: number; // Time elapsed (in milliseconds) between client issuing query and database responding - not only time taken to run query target: string; }; ``` Note that for MongoDB, the `params` and `duration` fields will be undefined. All other log level event types: ```ts file=index.d.ts export type LogEvent = { timestamp: Date; message: string; target: string; }; ``` #### Examples ##### Log `query` and `info` to `stdout` ```ts highlight=3;normal; import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient({ log: ['query', 'info'] }); async function main() { const countUsers = await prisma.user.count({}); } main() .then(async () => { await prisma.$disconnect(); }) .catch(async (e) => { console.error(e); await prisma.$disconnect(); process.exit(1); }); ``` ```code no-copy prisma:info Starting a postgresql pool with 13 connections. prisma:info Started http server prisma:query SELECT COUNT(*) FROM (SELECT "public"."User"."id" FROM "public"."User" WHERE 1=1 ORDER BY "public"."User"."coinflips" ASC OFFSET $1) AS "sub" ``` ##### Log a `query` event to console ```ts import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient({ log: [{ level: 'query', emit: 'event' }], }); prisma.$on('query', (e) => { console.log(e); }); async function main() { const countUsers = await prisma.user.count({}); } main() .then(async () => { await prisma.$disconnect(); }) .catch(async (e) => { console.error(e); await prisma.$disconnect(); process.exit(1); }); ``` ```js no-copy { timestamp: 2020-11-17T10:32:10.898Z, query: 'SELECT COUNT(*) FROM (SELECT "public"."User"."id" FROM "public"."User" WHERE 1=1 OFFSET $1) AS "sub"', params: '[0]', duration: 5, target: 'quaint::connector::metrics' } ``` ##### Log `info`, `warn`, and `error` events to console ```ts import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient({ log: [ { level: 'warn', emit: 'event' }, { level: 'info', emit: 'event' }, { level: 'error', emit: 'event' }, ], }); prisma.$on('warn', (e) => { console.log(e); }); prisma.$on('info', (e) => { console.log(e); }); prisma.$on('error', (e) => { console.log(e); }); async function main() { const countUsers = await prisma.user.count({}); } main() .then(async () => { await prisma.$disconnect(); }) .catch(async (e) => { console.error(e); await prisma.$disconnect(); process.exit(1); }); ``` ```js no-copy { timestamp: 2020-11-17T10:33:24.592Z, message: 'Starting a postgresql pool with 13 connections.', target: 'quaint::pooled' } { timestamp: 2020-11-17T10:33:24.637Z, message: 'Started http server', target: 'query_engine::server' } ``` ### `errorFormat` Determines the level and formatting of errors returned by Prisma Client. #### Error formats | Name | Description | | --------------------- | ---------------------------------------------- | | `undefined` | If it's not defined, the default is colorless. | | `pretty` | Enables pretty error formatting. | | `colorless` (default) | Enables colorless error formatting. | | `minimal` | Enables minimal error formatting. | #### Examples ##### No error formatting ```ts const prisma = new PrismaClient({ // Defaults to colorless }); ``` ##### `pretty` error formatting ```ts const prisma = new PrismaClient({ errorFormat: 'pretty', }); ``` ##### `colorless` error formatting ```ts const prisma = new PrismaClient({ errorFormat: 'colorless', }); ``` ##### `minimal` error formatting ```ts const prisma = new PrismaClient({ errorFormat: 'minimal', }); ``` ### `adapter` Defines an instance of a [driver adapter](/orm/overview/databases/database-drivers#driver-adapters). See also [Database drivers](/orm/overview/databases/database-drivers) . :::info This is available from version 5.4.0 and newer behind the `driverAdapters` feature flag. ::: #### Example The example below uses the [Neon driver adapter](/orm/overview/databases/neon#how-to-use-neons-serverless-driver-with-prisma-orm-preview) ```ts import { PrismaNeon } from '@prisma/adapter-neon'; import { PrismaClient } from '@prisma/client'; import dotenv from 'dotenv'; dotenv.config(); const connectionString = `${process.env.DATABASE_URL}`; const adapter = new PrismaNeon({ connectionString }); const prisma = new PrismaClient({ adapter }); ``` ### `rejectOnNotFound` **Note**: `rejectOnNotFound` was removed in v5.0.0. **Deprecated:** `rejectOnNotFound` is deprecated in v4.0.0. From v4.0.0, use the queries [`findUniqueOrThrow`](#finduniqueorthrow) or [`findFirstOrThrow`](#findfirstorthrow). Use the `rejectOnNotFound` parameter to configure `findUnique()` and/or `findFirst` to throw an error if the record was not found. By default, both operations return `null` if the record is not found. #### Remarks - You can configure `rejectOnNotFound` on a per-request level for both [`findUnique()`](#findunique) and [`findFirst`](#findfirst) #### Options | Option | Description | | -------------------- | ------------------------------------------------------------------------------------------- | | `RejectOnNotFound` | Enable globally (`true` / `false`) _or_ throw a custom error. | | `RejectPerOperation` | Enable per operation (`true` / `false`) _or_ throw a custom error per operation, per model. | #### Examples ##### Enable globally for `findUnique()` and `findFirst` ```ts const prisma = new PrismaClient({ rejectOnNotFound: true, }); ``` ##### Enable globally for a specific operation ```ts const prisma = new PrismaClient({ rejectOnNotFound: { findUnique: true, }, }); ``` ##### Throw a custom error per model and operation if record is not found ```ts const prisma = new PrismaClient({ rejectOnNotFound: { findFirst: { User: (err) => new Error('User error'), Post: (err) => new Error('Post error!'), }, findUnique: { User: (err) => new Error('User error'), Post: (err) => new Error('Post error!'), }, }, }); ``` ### `transactionOptions` **Note**: `transactionOptions` was introduced in v5.10.0. Allows to set [transaction options](/orm/prisma-client/queries/transactions#transaction-options) globally on the constructor level. #### Remarks - The transaction levels can be overridden on a per-transaction level. #### Options | Option | Description | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `maxWait` | The maximum amount of time Prisma Client will wait to acquire a transaction from the database. The default value is 2 seconds. | | `timeout` | The maximum amount of time the interactive transaction can run before being canceled and rolled back. The default value is 5 seconds. | | `isolationLevel` | Sets the [transaction isolation level](/orm/prisma-client/queries/transactions#transaction-isolation-level). By default this is set to the value currently configured in your database. The available can vary depending on the database you use. | #### Example ```ts const prisma = new PrismaClient({ transactionOptions: { isolationLevel: Prisma.TransactionIsolationLevel.Serializable, maxWait: 5000, // default: 2000 timeout: 10000, // default: 5000 }, }); ``` ## Model queries Use model queries to perform CRUD operations on your models. See also: [CRUD](/orm/prisma-client/queries/crud) > **Note**: It's a best practice to always validate and sanitize any untrusted user data before passing it into Prisma queries. Failure to do so can lead to SQL injection or other injection vulnerabilities if the type checks are bypassed. Make sure user-supplied values cannot inadvertently bypass critical checks. We strongly recommend performing type checking and input validation at the application layer. For more details, see [Custom Validation](/orm/prisma-client/queries/custom-validation) section. ### `findUnique()` `findUnique()` query lets you retrieve a single database record: - By _ID_ - By a _unique_ attribute `findUnique()` replaced `findOne` in version [2.12.0](https://github.com/prisma/prisma/releases/tag/2.12.0). #### Remarks - Prisma Client's dataloader [automatically batches `findUnique()` queries](/orm/prisma-client/queries/query-optimization-performance#solving-n1-in-graphql-with-findunique-and-prisma-clients-dataloader) with the same `select` and `where` parameters. - If you want the query to throw an error if the record is not found, then consider using [`findUniqueOrThrow`](#finduniqueorthrow) instead. - You cannot use [filter conditions](#filter-conditions-and-operators) (e.g. `equals`, `contains`, `not`) to filter fields of the [JSON](/orm/reference/prisma-schema-reference#json) data type. Using filter conditions will likely result in a `null` response for that field. #### Options | Name | Example type (`User`) | Required | Description | | ------------------------------- | ------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `where` | `UserWhereUniqueInput` | **Yes** | Wraps all fields of a model so that a record can be selected ([learn more](#filter-on-non-unique-fields-with-userwhereuniqueinput)).

Before version 4.5.0, this type only wraps _unique_ fields of a model. | | `select` | `XOR` | No | [Specifies which properties to include](/orm/prisma-client/queries/select-fields) on the returned object. | | `include` | `XOR` | No | [Specifies which relations should be eagerly loaded](/orm/prisma-client/queries/relation-queries) on the returned object. | | `omit` | `XOR` | No | Specifies which properties to exclude on the returned object. In [Preview](/orm/more/releases#preview) since 5.13.0 | | `relationLoadStrategy` | `'join'` or `'query'` | No | **Default: `join`**. Specifies the [load strategy](/orm/prisma-client/queries/relation-queries#relation-load-strategies-preview) for a relation query. Only available in combination with `include` (or `select` on a relation field). In [Preview](/orm/more/releases#preview) since 5.9.0. | #### Return type | Return type | Example | Description | | ------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | JavaScript object (typed) | `User` | | | JavaScript object (plain) | `{ title: "Hello world" }` | Use `select` and `include` to determine which fields to return. | | `null` | `null` | Record not found | #### Examples ##### Get the `User` record with an `id` of `42` ```ts const result = await prisma.user.findUnique({ where: { id: 42, }, }); ``` ##### Get the `User` record with an `email` of `alice@prisma.io` ```ts const result = await prisma.user.findUnique({ where: { email: 'alice@prisma.io', }, }); ``` ##### Get the `User` record with `firstName` of `Alice` and `lastName` of `Smith` (`@@unique`)
Expand for example User model with a @@unique block ```prisma model User { firstName String lastName String @@unique(fields: [firstName, lastName], name: "fullname") } ```
```ts const result = await prisma.user.findUnique({ where: { fullname: { // name property of @@unique attribute - default is firstname_lastname firstName: 'Alice', lastName: 'Smith', }, }, }); ``` ##### Get the `User` record with `firstName` of `Alice` and `lastName` of `Smith` (`@@id`)
Expand for example User model with an @@id block ```prisma model User { firstName String lastName String @@id([firstName, lastName]) } ```
```ts const result = await prisma.user.findUnique({ where: { firstName_lastName: { firstName: 'Alice', lastName: 'Smith', }, }, }); ``` ### `findUniqueOrThrow()` `findUniqueOrThrow()` retrieves a single record in the same way as [`findUnique()`](#findunique). However, if the query does not find the requested record, it throws a `PrismaClientKnownRequestError`. Note that [before Prisma v6](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6#removed-notfounderror), it would throw a `NotFoundError: No User found error`. Here’s an example of its usage: ```ts await prisma.user.findUniqueOrThrow({ where: { id: 1 }, }); ``` `findUniqueOrThrow()` differs from `findUnique()` as follows: - Its return type is non-nullable. For example, `post.findUnique()` can return `post` or `null`, but `post.findUniqueOrThrow()` always returns `post`. - It is not compatible with sequential operations in the [`$transaction` API](/orm/prisma-client/queries/transactions#the-transaction-api). If the query throws a `PrismaClientKnownRequestError`, then the API will not roll back any operations in the array of calls. As a workaround, you can use interactive transactions with the `$transaction` API, as follows: ```ts $transaction(async (prisma) => { await prisma.model.create({ data: { ... }); await prisma.model.findUniqueOrThrow(); }) ``` ### `findFirst()` `findFirst` returns the first record in a list that matches your criteria. #### Remarks - If you want the query to throw an error if the record is not found, then consider using [`findFirstOrThrow`](#findfirstorthrow) instead. #### Options | Name | Example type (`User`) | Required | Description | | ---------------------- | ----------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `select` | `XOR` | No | [Specifies which properties to include](/orm/prisma-client/queries/select-fields) on the returned object. | | `include` | `XOR` | No | [Specifies which relations should be eagerly loaded](/orm/prisma-client/queries/relation-queries) on the returned object. | | `omit` | `XOR` | No | Specifies which properties to exclude on the returned object. In [Preview](/orm/more/releases#preview) since 5.13.0. | | `relationLoadStrategy` | `'join'` or `'query'` | No | **Default: `join`**. Specifies the [load strategy](/orm/prisma-client/queries/relation-queries#relation-load-strategies-preview) for a relation query. Only available in combination with `include` (or `select` on a relation field). In [Preview](/orm/more/releases#preview) since 5.9.0. | | `where` | `UserWhereInput` | No | Wraps _all_ model fields in a type so that the list can be filtered by any property. | | `orderBy` | `XOR, UserOrderByInput>` | No | Lets you order the returned list by any property. | #### Return type | Return type | Example | Description | | ------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | JavaScript object (typed) | `User` | Specifies which properties to include on the returned object. | | JavaScript object (plain) | `{ title: "Hello world" }` | Use `select` and `include` to determine which fields to return. | | `null` | `null` | Record not found | #### Remarks - `findFirst` calls `findMany` behind the scenes and accepts the same query options. - Passing in a negative `take` value when you use a `findFirst` query reverses the order of the list. #### Examples See [Filter conditions and operators](#filter-conditions-and-operators) for examples of how to filter results. ##### Get the first `User` record where the `name` is `Alice` ```ts const user = await prisma.user.findFirst({ where: { name: 'Alice' }, }); ``` ##### Get the first `Post` record where the `title` starts with `A test`, reverse the list with `take` ```ts import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient({}); async function main() { const a = await prisma.post.create({ data: { title: 'A test 1', }, }); const b = await prisma.post.create({ data: { title: 'A test 2', }, }); const c = await prisma.post.findFirst({ where: { title: { startsWith: 'A test', }, }, orderBy: { title: 'asc', }, take: -1, // Reverse the list }); } main(); ``` ### `findFirstOrThrow()` `findFirstOrThrow()` retrieves a single data record in the same way as [`findFirst()`](#findfirst). However, if the query does not find a record, it throws a `PrismaClientKnownRequestError`. Note that [before Prisma v6](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6#removed-notfounderror), it would throw a `NotFoundError: No User found error`. `findFirstOrThrow()` differs from `findFirst()` as follows: - Its return type is non-nullable. For example, `post.findFirst()` can return `post` or `null`, but `post.findFirstOrThrow` always returns `post`. - It is not compatible with sequential operations in the [`$transaction` API](/orm/prisma-client/queries/transactions#the-transaction-api). If the query returns `PrismaClientKnownRequestError`, then the API will not roll back any operations in the array of calls. As a workaround, you can use interactive transactions with the `$transaction` API, as follows: ```ts prisma.$transaction(async (tx) => { await tx.model.create({ data: { ... }); await tx.model.findFirstOrThrow(); }) ``` ### `findMany()` `findMany` returns a list of records. #### Options | Name | Type | Required | Description | | ---------------------- | ------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `select` | `XOR` | No | [Specifies which properties to include](/orm/prisma-client/queries/select-fields) on the returned object. | | `include` | `XOR` | No | [Specifies which relations should be eagerly loaded](/orm/prisma-client/queries/relation-queries) on the returned object. | | `omit` | `XOR` | No | Specifies which properties to exclude on the returned object. In [Preview](/orm/more/releases#preview) since 5.13.0 | | `relationLoadStrategy` | `'join'` or `'query'` | No | **Default: `join`**. Specifies the [load strategy](/orm/prisma-client/queries/relation-queries#relation-load-strategies-preview) for a relation query. Only available in combination with `include` (or `select` on a relation field). In [Preview](/orm/more/releases#preview) since 5.9.0. | | `where` | `UserWhereInput` | No | Wraps _all_ model fields in a type so that the list can be filtered by any property. | | `orderBy` | `XOR`ByInput>, PostOrderByInput>` | No | Lets you order the returned list by any property. | | `cursor` | `UserWhereUniqueInput` | No | Specifies the position for the list (the value typically specifies an `id` or another unique value). | | `take` | `number` | No | Specifies how many objects should be returned in the list (as seen from the _beginning_ (positive value) or _end_ (negative value) **either** of the list **or** from the `cursor` position if mentioned) | | `skip` | `number` | No | Specifies how many of the returned objects in the list should be skipped. | | `distinct` | `Enumerable` | No | Lets you filter out duplicate rows by a specific field - for example, return only distinct `Post` titles. | #### Return type | Return type | Example | Description | | ------------------------------- | ---------------------------- | --------------------------------------------------------------- | | JavaScript array object (typed) | `User[]` | | | JavaScript array object (plain) | `[{ title: "Hello world" }]` | Use `select` and `include` to determine which fields to return. | | Empty array | `[]` | No matching records found. | #### Examples See [Filter conditions and operators](#filter-conditions-and-operators) for examples of how to filter results. ##### Get all `User` records where the `name` is `Alice` ```ts const user = await prisma.user.findMany({ where: { name: 'Alice' }, }); ``` ### `create()` `create` creates a new database record. #### Options | Name | Type | Required | Description | | ----------------------- | -------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `data` | `XOR`UserUncheckedCreateInput>` | **Yes** | Wraps all the model fields in a type so that they can be provided when creating new records. It also includes relation fields which lets you perform (transactional) nested inserts. Fields that are marked as optional or have default values in the datamodel are optional. | | [`select`](#select) | `XOR` | No | [Specifies which properties to include](/orm/prisma-client/queries/select-fields) on the returned object. | | [`include`](#include) | `XOR` | No | [Specifies which relations should be eagerly loaded](/orm/prisma-client/queries/relation-queries) on the returned object. | | [`omit`](#omit) | `XOR` | No | Specifies which properties to exclude on the returned object. In [Preview](/orm/more/releases#preview) since 5.13.0 | | `relationLoadStrategy` | `'join'` or `'query'` | No | **Default: `join`**. Specifies the [load strategy](/orm/prisma-client/queries/relation-queries#relation-load-strategies-preview) for a relation query. Only available in combination with `include` (or `select` on a relation field). In [Preview](/orm/more/releases#preview) since 5.9.0. | #### Return type | Return type | Example | Description | | ------------------------- | ------------------------------ | --------------------------------------------------------------- | | JavaScript object (typed) | `User` | | | JavaScript object (plain) | `{ name: "Alice Wonderland" }` | Use `select` and `include` to determine which fields to return. | #### Remarks - You can also perform a nested [`create`](#create-1) - for example, add a `User` and two `Post` records at the same time. #### Examples ##### Create a single new record with the only required field `email` ```ts const user = await prisma.user.create({ data: { email: 'alice@prisma.io' }, }); ``` ##### Create multiple new records In most cases, you can carry out batch inserts with the [`createMany()`](#createmany) or [`createManyAndReturn()`](#createmanyandreturn) queries. However, [there are scenarios where `create()` is the best option to insert multiple records](#remarks-11). The following example results in **two** `INSERT` statements: ```ts import { Prisma, PrismaClient } from '@prisma/client'; const prisma = new PrismaClient({ log: ['query'] }); async function main() { let users: Prisma.UserCreateInput[] = [ { email: 'ariana@prisma.io', name: 'Ari', profileViews: 20, coinflips: [true, false, false], role: 'ADMIN', }, { email: 'elsa@prisma.io', name: 'Elsa', profileViews: 20, coinflips: [true, false, false], role: 'ADMIN', }, ]; await Promise.all( users.map(async (user) => { await prisma.user.create({ data: user, }); }) ); } main() .then(async () => { await prisma.$disconnect(); }) .catch(async (e) => { console.error(e); await prisma.$disconnect(); process.exit(1); }); ``` ```sql no-copy prisma:query BEGIN prisma:query INSERT INTO "public"."User" ("name","email","profileViews","role","coinflips") VALUES ($1,$2,$3,$4,$5) RETURNING "public"."User"."id" prisma:query SELECT "public"."User"."id", "public"."User"."name", "public"."User"."email", "public"."User"."profileViews", "public"."User"."role", "public"."User"."coinflips" FROM "public"."User" WHERE "public"."User"."id" = $1 LIMIT $2 OFFSET $3 prisma:query INSERT INTO "public"."User" ("name","email","profileViews","role","coinflips") VALUES ($1,$2,$3,$4,$5) RETURNING "public"."User"."id" prisma:query COMMIT prisma:query SELECT "public"."User"."id", "public"."User"."name", "public"."User"."email", "public"."User"."profileViews", "public"."User"."role", "public"."User"."coinflips" FROM "public"."User" WHERE "public"."User"."id" = $1 LIMIT $2 OFFSET $3 prisma:query COMMIT ``` ### `update()` `update` updates an existing database record. #### Options | Name | Type | Required | Description | | ----------------------- | ------------------------------------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `data` | `XOR`UserUncheckedUpdateInput>` | **Yes** | Wraps all the fields of the model so that they can be provided when updating an existing record. Fields that are marked as optional or have default values in the datamodel are optional. | | `where` | `UserWhereUniqueInput` | **Yes** | Wraps all fields of a model so that a record can be selected ([learn more](#filter-on-non-unique-fields-with-userwhereuniqueinput)).

Before version 4.5.0, this type only wraps _unique_ fields of a model. | | [`select`](#select) | `XOR` | No | [Specifies which properties to include](/orm/prisma-client/queries/select-fields) on the returned object. | | [`include`](#include) | `XOR` | No | [Specifies which relations should be eagerly loaded](/orm/prisma-client/queries/relation-queries) on the returned object. | | [`omit`](#omit) | `XOR` | No | Specifies which properties to exclude on the returned object. In [Preview](/orm/more/releases#preview) since 5.13.0. | | `relationLoadStrategy` | `'join'` or `'query'` | No | **Default: `join`**. Specifies the [load strategy](/orm/prisma-client/queries/relation-queries#relation-load-strategies-preview) for a relation query. Only available in combination with `include` (or `select` on a relation field). In [Preview](/orm/more/releases#preview) since 5.9.0. | #### Return type | Return type | Example | Description | | -------------------------- | ------------------------------ | --------------------------------------------------------------- | | JavaScript object (typed) | `User` | | | JavaScript object (plain) | `{ name: "Alice Wonderland" }` | Use `select` and `include` to determine which fields to return. | | `RecordNotFound` exception | | Exception is thrown if record does not exist. | #### Remarks - To perform arithmetic operations on update (add, subtract, multiply, divide), use [atomic updates](#atomic-number-operations) to prevent race conditions. - You can also perform a nested [`update`](#update-1) - for example, update a user and that user's posts at the same time. #### Examples ##### Update the `email` of the `User` record with `id` of `1` to `alice@prisma.io` ```ts const user = await prisma.user.update({ where: { id: 1 }, data: { email: 'alice@prisma.io' }, }); ``` ### `upsert()` This section covers the usage of the `upsert()` operation. To learn about using [nested upsert queries](#upsert-1) within `update()`, reference the linked documentation. `upsert` does the following: - If an existing database record satisfies the `where` condition, it updates that record - If no database record satisfies the `where` condition, it creates a new database record #### Options | Name | Type | Required | Description | | ----------------------- | ------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `create` | `XOR`UserUncheckedCreateInput>` | **Yes** | Wraps all the fields of the model so that they can be provided when creating new records. It also includes relation fields which lets you perform (transactional) nested inserts. Fields that are marked as optional or have default values in the datamodel are optional. | | `update` | `XOR`UserUncheckedUpdateInput>` | **Yes** | Wraps all the fields of the model so that they can be provided when updating an existing record. Fields that are marked as optional or have default values in the datamodel are optional. | | `where` | `UserWhereUniqueInput` | **Yes** | Wraps all fields of a model so that a record can be selected ([learn more](#filter-on-non-unique-fields-with-userwhereuniqueinput)).

Before version 4.5.0, this type only wraps _unique_ fields of a model. | | [`select`](#select) | `XOR` | No | [Specifies which properties to include](/orm/prisma-client/queries/select-fields) on the returned object. | | [`include`](#include) | `XOR` | No | [Specifies which relations should be eagerly loaded](/orm/prisma-client/queries/relation-queries) on the returned object. | | [`omit`](#omit) | `XOR` | No | Specifies which properties to exclude on the returned object. In [Preview](/orm/more/releases#preview) since 5.13.0 | | `relationLoadStrategy` | `'join'` or `'query'` | No | **Default: `join`**. Specifies the [load strategy](/orm/prisma-client/queries/relation-queries#relation-load-strategies-preview) for a relation query. Only available in combination with `include` (or `select` on a relation field). In [Preview](/orm/more/releases#preview) since 5.9.0. | #### Return type | Return type | Example | Description | | ------------------------- | ------------------------------ | --------------------------------------------------------------- | | JavaScript object (typed) | `User` | | | JavaScript object (plain) | `{ name: "Alice Wonderland" }` | Use `select` and `include` to determine which fields to return. | #### Remarks - To perform arithmetic operations on update (add, subtract, multiply, divide), use [atomic updates](#atomic-number-operations) to prevent race conditions. - If two or more upsert operations happen at the same time and the record doesn't already exist, then a race condition might happen. As a result, one or more of the upsert operations might throw a unique key constraint error. Your application code can catch this error and retry the operation. [Learn more](#unique-key-constraint-errors-on-upserts). - From version 4.6.0, Prisma ORM hands over upsert queries to the database where possible. [Learn more](#database-upserts). #### Examples ##### Update (if exists) or create a new `User` record with an `email` of `alice@prisma.io` ```ts const user = await prisma.user.upsert({ where: { id: 1 }, update: { email: 'alice@prisma.io' }, create: { email: 'alice@prisma.io' }, }); ``` #### Unique key constraint errors on upserts ##### Problem If multiple upsert operations happen at the same time and the record doesn't already exist, then one or more of the operations might return a [unique key constraint error](/orm/reference/error-reference#p2002). ##### Cause When Prisma Client does an upsert, it first checks whether that record already exists in the database. To make this check, Prisma Client performs a read operation with the `where` clause from the upsert operation. This has two possible outcomes, as follows: - If the record does not exist, then Prisma Client creates that record. - If the record exists, then Prisma Client updates it. When your application tries to perform two or more concurrent upsert operations, then a race condition might happen where two or more operations do not find the record and therefore try to create that record. In this situation, one of the operations successfully creates the new record but the other operations fail and return a unique key constraint error. ##### Solution Handle the P2002 error in your application code. When it occurs, retry the upsert operation to update the row. #### Database upserts Where possible, Prisma Client hands over an `upsert` query to the database. This is called a _database upsert_. Database upserts have the following advantages: - They are faster than upserts handled by Prisma Client - [Unique key constraint errors](#unique-key-constraint-errors-on-upserts) cannot happen Prisma Client uses a database upsert automatically when [specific criteria](#database-upsert-query-criteria) are met. When these criteria are not met, Prisma Client handles the `upsert`. To use a database upsert, Prisma Client sends the SQL construction [`INSERT ... ON CONFLICT SET .. WHERE`](https://www.prisma.io/dataguide/postgresql/inserting-and-modifying-data/insert-on-conflict) to the database. ##### Database upsert prerequisites Prisma Client can use database upserts if your stack meets the following criteria: - You use Prisma ORM version 4.6.0 or later - Your application uses a CockroachDB, PostgreSQL, or SQLite data source ##### Database upsert query criteria Prisma Client uses a database upsert for an `upsert` query when the query meets the following criteria: - There are no nested queries in the `upsert`'s `create` and `update` [options](#options-7) - The query does _not_ include a selection that uses a [nested read](/orm/prisma-client/queries/relation-queries#nested-reads) - The query modifies only one model - There is only one unique field in the `upsert`'s `where` option - The unique field in the `where` option and the unique field in the `create` option have the same value If your query does not meet these criteria, then Prisma Client handles the upsert itself. ##### Database upsert examples The following examples use this schema: ```prisma model User { id Int @id profileViews Int userName String @unique email String @@unique([id, profileViews]) } ``` The following `upsert` query meets all of the criteria, so Prisma Client uses a database upsert. ```ts prisma.user.upsert({ where: { userName: 'Alice', }, create: { id: 1, profileViews: 1, userName: 'Alice', email: 'alice@prisma.io', }, update: { email: 'updated@example.com', }, }); ``` In this situation, Prisma uses the following SQL query: ```sql INSERT INTO "public"."User" ("id","profileViews","userName","email") VALUES ($1,$2,$3,$4) ON CONFLICT ("userName") DO UPDATE SET "email" = $5 WHERE ("public"."User"."userName" = $6 AND 1=1) RETURNING "public"."User"."id", "public"."User"."profileViews", "public"."User"."userName", "public"."User"."email" ``` The following query has multiple unique values in the `where` clause, so Prisma Client does _not_ use a database upsert: ```ts prisma.User.upsert({ where: { userName: 'Alice', profileViews: 1, id: 1, }, create: { id: 1, profileViews: 1, userName: 'Alice', email: 'alice@prisma.io', }, update: { email: 'updated@example.com', }, }); ``` In the following query, the values for `userName` in the `where` and `create` options are different, so Prisma Client does _not_ use a database upsert. ```ts prisma.User.upsert({ where: { userName: 'Alice', }, create: { id: 1, profileViews: 1, userName: 'AliceS', email: 'alice@prisma.io', }, update: { email: 'updated@example.com', }, }); ``` In the following query, the selection on the `title` field in `posts` is a nested read, so Prisma Client does _not_ use a database upsert. ```ts prisma.user.upsert({ select: { email: true, id: true, posts: { select: { title: true, }, }, }, where: { userName: 'Alice', }, create: { id: 1, profileViews: 1, userName: 'Alice', email: 'alice@prisma.io', }, update: { email: 'updated@example.com', }, }); ``` ### `delete()` `delete` deletes an existing database record. You can delete a record: - By _ID_ - By a _unique_ attribute To delete records that match a certain criteria, use [`deleteMany`](#deletemany) with a filter. #### Options | Name | Type | Required | Description | | ----------------------- | ------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `where` | `UserWhereUniqueInput` | **Yes** | Wraps all fields of a model so that a record can be selected ([learn more](#filter-on-non-unique-fields-with-userwhereuniqueinput)).

Before version 4.5.0, this type only wraps _unique_ fields of a model. | | [`select`](#select) | `XOR` | No | [Specifies which properties to include](/orm/prisma-client/queries/select-fields) on the returned object. | | [`include`](#include) | `XOR` | No | [Specifies which relations should be eagerly loaded](/orm/prisma-client/queries/relation-queries) on the returned object. | | [`omit`](#omit) | `XOR` | No | Specifies which properties to exclude on the returned object. In [Preview](/orm/more/releases#preview) since 5.13.0 | | `relationLoadStrategy` | `'join'` or `'query'` | No | **Default: `join`**. Specifies the [load strategy](/orm/prisma-client/queries/relation-queries#relation-load-strategies-preview) for a relation query. Only available in combination with `include` (or `select` on a relation field). In [Preview](/orm/more/releases#preview) since 5.9.0. | #### Return type | Return type | Example | Description | | -------------------------- | ------------------------------ | ------------------------------------------------------------------------------------------------------------- | | JavaScript object (typed) | `User` | The `User` record that was deleted. | | JavaScript object (plain) | `{ name: "Alice Wonderland" }` | Data from the `User` record that was deleted. Use `select` and `include` to determine which fields to return. | | `RecordNotFound` exception | | Throws an exception if record does not exist. | #### Remarks - To delete multiple records based on some criteria (for example, all `User` records with a `prisma.io` email address, use `deleteMany`) #### Examples ##### Delete the `User` record with an `id` of `1` ```ts const user = await prisma.user.delete({ where: { id: 1 }, }); ``` ##### Delete the `User` record where `email` equals `else@prisma.io` The following query deletes a specific user record and uses `select` to return the `name` and `email` of the deleted user: ```ts const deleteUser = await prisma.user.delete({ where: { email: 'elsa@prisma.io', }, select: { email: true, name: true, }, }); ``` ```json no-copy { "email": "elsa@prisma.io", "name": "Elsa" } ``` ### `createMany()` `createMany` creates multiple records in a transaction. #### Options | Name | Type | Required | Description | | ----------------- | --------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `data` | `Enumerable` | **Yes** | Wraps all the model fields in a type so that they can be provided when creating new records. Fields that are marked as optional or have default values in the datamodel are optional. | | `skipDuplicates?` | `boolean` | No | Do not insert records with unique fields or ID fields that already exist. Only supported by databases that support [`ON CONFLICT DO NOTHING`](https://www.postgresql.org/docs/9.5/sql-insert.html#SQL-ON-CONFLICT). This excludes MongoDB and SQLServer | #### Return type | Return type | Example | Description | | -------------- | -------------- | ----------------------------------------- | | `BatchPayload` | `{ count: 3 }` | A count of the number of records created. | #### Remarks - As of Prisma ORM version 5.12.0, `createMany()` is now supported by SQLite. - The `skipDuplicates` option is not supported by MongoDB, SQLServer, or SQLite. - You **cannot** create or connect relations by using nested `create`, `createMany`, `connect`, `connectOrCreate` queries inside a top-level `createMany()` query. See here for a [workaround](/orm/prisma-client/queries/relation-queries#using-nested-createmany). - You can use a nested [`createMany`](#createmany-1) query inside an [`update()`](#update) or [`create()`](#create) query - for example, add a `User` and two `Post` records with a nested `createMany` at the same time. #### Examples ##### Create several new users ```ts const users = await prisma.user.createMany({ data: [ { name: 'Sonali', email: 'sonali@prisma.io' }, { name: 'Alex', email: 'alex@prisma.io' }, ], }); ``` ### `createManyAndReturn()` `createManyAndReturn` creates multiple records and returns the resulting objects. :::info This feature is available in Prisma ORM version 5.14.0 and later for PostgreSQL, CockroachDB and SQLite. ::: #### Options | Name | Type | Required | Description | | ----------------- | --------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `data` | `Enumerable` | **Yes** | Wraps all the model fields in a type so that they can be provided when creating new records. Fields that are marked as optional or have default values in the datamodel are optional. | | [`select`](#select) | `XOR` | No | [Specifies which properties to include](/orm/prisma-client/queries/select-fields) on the returned objects. | | [`omit`](#omit) | `XOR` | No | Specifies which properties to exclude on the returned objects. In [Preview](/orm/more/releases#preview) since 5.13.0. Mutually exclusive with `select`. | | [`include`](#include) | `XOR` | No | [Specifies which relations should be eagerly loaded](/orm/prisma-client/queries/relation-queries) on the returned objects. | | `skipDuplicates?` | `boolean` | No | Do not insert records with unique fields or ID fields that already exist. Only supported by databases that support [`ON CONFLICT DO NOTHING`](https://www.postgresql.org/docs/9.5/sql-insert.html#SQL-ON-CONFLICT). This excludes MongoDB and SQLServer | #### Remarks - The `skipDuplicates` option is not supported by SQLite. - Note that the order of elements returned by `createManyAndReturn` is not guaranteed. - You **cannot** create or connect relations by using nested `create`, `createMany`, `connect`, `connectOrCreate` queries inside a top-level `createManyAndReturn()` query. See here for a [workaround](/orm/prisma-client/queries/relation-queries#using-nested-createmany). - When relations are included via `include`, a separate query is generated per relation. - `relationLoadStrategy: join` is not supported. #### Return type | Return type | Example | Description | | ----------- | ------- | ----------- | | JavaScript array object (typed) | `User[]` | | | JavaScript array object (plain) | `[{ name: "Sonali" }]` | Use `select`, `omit` and `include` to determine which fields to return. | #### Examples ##### Create and return several new users ```ts const users = await prisma.user.createManyAndReturn({ data: [ { name: 'Sonali', email: 'sonali@prisma.io' }, { name: 'Alex', email: 'alex@prisma.io' }, ], }) ``` ```json no-copy [ { "id": 0, "name": "Sonali", "email": "sonali@prisma.io", "profileViews": 0 }, { "id": 1, "name": "Alex", "email": "alex@prisma.io", "profileViews": 0 } ] ``` ### `updateMany()` `updateMany` updates a batch of existing database records in bulk and returns the number of updated records. #### Options | Name | Type | Required | Description | | ------- | ----------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `data` | `XOR`UserUncheckedUpdateManyInput>` | **Yes** | Wraps all the fields of the model so that they can be provided when updating an existing record. Fields that are marked as optional or have default values in the datamodel are optional on `data`. | | `where` | `UserWhereInput` | No | Wraps _all_ fields of a model so that the list can be filtered by any property. If you do not filter the list, all records will be updated. | | `limit` | `number` | No | Limits the number of records to update. | #### Return type | Return type | Example | Description | | -------------- | -------------- | ----------------------------- | | `BatchPayload` | `{ count: 4 }` | The count of updated records. | ```ts export type BatchPayload = { count: number; }; ``` #### Examples ##### Update all `User` records where the `name` is `Alice` to `ALICE` ```ts const updatedUserCount = await prisma.user.updateMany({ where: { name: 'Alice' }, data: { name: 'ALICE' }, }); ``` ##### Update all `User` records where the `email` contains `prisma.io` and at least one related `Post` has more than 10 likes ```ts const updatedUserCount = await prisma.user.updateMany({ where: { email: { contains: 'prisma.io', }, posts: { some: { likes: { gt: 10, }, }, }, }, data: { role: 'USER', }, }); ``` ##### Update `User` records where the `email` contains `prisma.io`, but limit to 5 records updated. ```ts const updatedUserCount = await prisma.user.updateMany({ where: { email: { contains: 'prisma.io', }, }, data: { role: 'USER', }, limit: 5, }); ``` ### `updateManyAndReturn()` :::info This feature is available in Prisma ORM version 6.2.0 and later for PostgreSQL, CockroachDB and SQLite. ::: `updateManyAndReturn` updates multiple records and returns the resulting objects. #### Options | Name | Type | Required | Description | | ------- | ----------------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `data` | `XOR`UserUncheckedUpdateManyInput>` | **Yes** | Wraps all the fields of the model so that they can be provided when updating an existing record. Fields that are marked as optional or have default values in the datamodel are optional on `data`. | | `where` | `UserWhereInput` | No | Wraps _all_ fields of a model so that the list can be filtered by any property. If you do not filter the list, all records will be updated. | #### Return type | Return type | Example | Description | | ----------- | ------- | ----------- | | JavaScript array object (typed) | `User[]` | | | JavaScript array object (plain) | `[{ name: "Sonali" }]` | Use `select`, `omit` and `include` to determine which fields to return. | #### Examples ##### Update and return multiple users ```ts const users = await prisma.user.updateManyAndReturn({ where: { email: { contains: 'prisma.io', } }, data: [ { role: 'ADMIN' } ], }) ``` ```json no-copy [ { "id": 0, "name": "Sonali", "email": "sonali@prisma.io", "role": "ADMIN", "profileViews": 0 }, { "id": 1, "name": "Alex", "email": "alex@prisma.io", "role": "ADMIN", "profileViews": 0 } ] ``` ### `deleteMany()` `deleteMany` deletes multiple records in a transaction. #### Options | Name | Type | Required | Description | | ------- | ---------------- | -------- | ---------------------------------------------------------------------------- | | `where` | `UserWhereInput` | No | Wraps _all_ fields of a model so that the list can be filtered by any field. | | `limit` | `Int` | No | Limits the number of records deleted. | #### Return type | Return type | Example | Description | | -------------- | -------------- | ----------------------------- | | `BatchPayload` | `{ count: 4 }` | The count of deleted records. | ```ts export type BatchPayload = { count: number; }; ``` #### Examples ##### Delete all `User` records ```ts const deletedUserCount = await prisma.user.deleteMany({}); ``` ##### Delete all `User` records where the `name` is `Alice` ```ts const deletedUserCount = await prisma.user.deleteMany({ where: { name: 'Alice' }, }); ``` ##### Delete all `User` records where the `email` contains `prisma.io`, but limit to 5 records deleted. ```ts const deletedUserCount = await prisma.user.deleteMany({ where: { email: { contains: 'prisma.io', }, }, limit: 5, }); ``` See [Filter conditions and operators](#filter-conditions-and-operators) for examples of how to filter the records to delete. ### `count()` #### Options | Name | Type | Required | Description | | --------- | ------------------------------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `where` | `UserWhereInput` | No | Wraps _all_ model fields in a type so that the list can be filtered by any property. | | `orderBy` | `XOR`ByInput>, PostOrderByInput>` | No | Lets you order the returned list by any property. | | `cursor` | `UserWhereUniqueInput` | No | Specifies the position for the list (the value typically specifies an `id` or another unique value). | | `take` | `number` | No | Specifies how many objects should be returned in the list (as seen from the _beginning_ (positive value) or _end_ (negative value) **either** of the list **or** from the `cursor` position if mentioned) | | `skip` | `number` | No | Specifies how many of the returned objects in the list should be skipped. | #### Return type | Return type | Example | Description | | ------------------------------ | ------------------------ | ----------------------------- | | `number` | `29` | The count of records. | | `UserCountAggregateOutputType` | `{ _all: 27, name: 10 }` | Returned if `select` is used. | #### Examples ##### Count all `User` records ```ts const result = await prisma.user.count(); ``` ##### Count all `User` records with at least one published `Post` ```ts const result = await prisma.user.count({ where: { post: { some: { published: true, }, }, }, }); ``` ##### Use `select` to perform three separate counts The following query returns: - A count of all records (`_all`) - A count of all records with non-`null` `name` fields - A count of all records with non-`null` `city` fields ```ts const c = await prisma.user.count({ select: { _all: true, city: true, name: true, }, }); ``` ### `aggregate()` See also: [Aggregation, grouping, and summarizing](/orm/prisma-client/queries/aggregation-grouping-summarizing#aggregate) #### Options | Name | Type | Required | Description | | --------- | ------------------------------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `where` | `UserWhereInput` | No | Wraps _all_ model fields in a type so that the list can be filtered by any property. | | `orderBy` | `XOR,`
`UserOrderByInput>` | No | Lets you order the returned list by any property. | | `cursor` | `UserWhereUniqueInput` | No | Specifies the position for the list (the value typically specifies an `id` or another unique value). | | `take` | `number` | No | Specifies how many objects should be returned in the list (as seen from the _beginning_ (positive value) or _end_ (negative value) **either** of the list **or** from the `cursor` position if mentioned) | | `skip` | `number` | No | Specifies how many of the returned objects in the list should be skipped. | | `_count` | `true` | No | Returns a count of matching records or non-`null` fields. | | `_avg` | `UserAvgAggregateInputType` | No | Returns an average of all values of the specified field. | | `_sum` | `UserSumAggregateInputType` | No | Returns the sum of all values of the specified field. | | `_min` | `UserMinAggregateInputType` | No | Returns the smallest available value of the specified field. | | `_max` | `UserMaxAggregateInputType` | No | Returns the largest available value of the specified field. | #### Examples ##### Return `_min`, `_max`, and `_count` of `profileViews` of all `User` records ```ts const minMaxAge = await prisma.user.aggregate({ _count: { _all: true, }, _max: { profileViews: true, }, _min: { profileViews: true, }, }); ``` ```js no-copy { _count: { _all: 29 }, _max: { profileViews: 90 }, _min: { profileViews: 0 } } ``` ##### Return `_sum` of all `profileViews` for all `User` records ```ts const setValue = await prisma.user.aggregate({ _sum: { profileViews: true, }, }); ``` ```js no-copy { "_sum": { "profileViews": 9493 } } ``` ### `groupBy()` See also: [Aggregation, grouping, and summarizing](/orm/prisma-client/queries/aggregation-grouping-summarizing#group-by) #### Options | Name | Type | Required | Description | | --------- | ------------------------------------------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `where` | `UserWhereInput` | No | Wraps _all_ model fields in a type so that the list can be filtered by any property. | | `orderBy` | `XOR,`
`UserOrderByInput>` | No | Lets you order the returned list by any property that is also present in `by`. | | `by` | `Array` \| `string` | No | Specifies the field or combination of fields to group records by. | | `having` | `UserScalarWhereWithAggregatesInput` | No | Allows you to filter groups by an aggregate value - for example, only return groups _having_ an average age less than 50. | | `take` | `number` | No | Specifies how many objects should be returned in the list (as seen from the _beginning_ (positive value) or _end_ (negative value) **either** of the list **or** from the `cursor` position if mentioned) | | `skip` | `number` | No | Specifies how many of the returned objects in the list should be skipped. | | `_count` | `true` \| `UserCountAggregateInputType` | No | Returns a count of matching records or non-`null` fields. | | `_avg` | `UserAvgAggregateInputType` | No | Returns an average of all values of the specified field. | | `_sum` | `UserSumAggregateInputType` | No | Returns the sum of all values of the specified field. | | `_min` | `UserMinAggregateInputType` | No | Returns the smallest available value of the specified field. | | `_max` | `UserMaxAggregateInputType` | No | Returns the largest available value of the specified field. | #### Examples ##### Group by `country`/`city` where the average `profileViews` is greater than `200`, and return the `_sum` of `profileViews` for each group The query also returns a count of `_all` records in each group, and all records with non-`null` `city` field values in each group. ```ts const groupUsers = await prisma.user.groupBy({ by: ['country', 'city'], _count: { _all: true, city: true, }, _sum: { profileViews: true, }, orderBy: { country: 'desc', }, having: { profileViews: { _avg: { gt: 200, }, }, }, }); ``` ```js no-copy [ { country: 'Denmark', city: 'Copenhagen', _sum: { profileViews: 490 }, _count: { _all: 70, city: 8, }, }, { country: 'Sweden', city: 'Stockholm', _sum: { profileViews: 500 }, _count: { _all: 50, city: 3, }, }, ]; ``` ### `findRaw()` See: [Using Raw SQL (`findRaw()`)](/orm/prisma-client/using-raw-sql/raw-queries#findraw). ### `aggregateRaw()` See: [Using Raw SQL (`aggregateRaw()`)](/orm/prisma-client/using-raw-sql/raw-queries#aggregateraw). ## Model query options ### `select` `select` defines which fields are included in the object that Prisma Client returns. See: [Select fields and include relations](/orm/prisma-client/queries/select-fields) . #### Remarks - You cannot combine `select` and `include` on the same level. - In [3.0.1](https://github.com/prisma/prisma/releases/3.0.1) and later, you can [select a `_count` of relations](#select-a-_count-of-relations). #### Examples ##### Select the `name` and `profileViews` fields of a single `User` record ```ts const result = await prisma.user.findUnique({ where: { id: 1 }, select: { name: true, profileViews: true, }, }); ``` ```js no-copy { name: "Alice", profileViews: 0 } ``` ##### Select the `email` and `role` fields of a multiple `User` records ```ts const result = await prisma.user.findMany({ select: { email: true, role: true, }, }); ``` ```js no-copy [ { email: 'alice@prisma.io', role: 'ADMIN', }, { email: 'bob@prisma.io', role: 'USER', }, ]; ``` ##### Select a `_count` of relations ```ts const usersWithCount = await prisma.user.findMany({ select: { _count: { select: { posts: true }, }, }, }); ``` ```js no-copy { _count: { posts: 3; } } ``` ##### Select the 'id' and 'title' fields of related `Post` records ```ts const result = await prisma.user.findMany({ select: { id: true, name: true, posts: { select: { id: true, title: true, }, }, }, }); ``` ```ts no-copy [ { id: 1, name: 'Alice', posts: [ { id: 1, title: 'Hello World' }, { id: 2, title: 'Bye bye' }, ], }, { id: 2, name: 'Bob', posts: [], }, ]; ``` ##### `include` inside `select` ```ts const result = await prisma.user.findMany({ select: { id: true, name: true, posts: { include: { author: true, }, }, }, }); ``` ```js no-copy [ { id: 1, name: 'Alice', posts: [ { id: 1, title: 'Hello World', published: true, author: { id: 1, name: 'Alice', email: 'alice@prisma.io', role: 'ADMIN', coinflips: [true, false], profileViews: 0, }, }, { id: 2, title: 'Bye bye', published: false, author: { id: 1, name: 'Alice', email: 'alice@prisma.io', role: 'USER', coinflips: [], profileViews: 0, }, }, ], }, ]; ``` #### Generated types for `select` The following example demonstrates how to use the [`validator`](/orm/prisma-client/type-safety/prisma-validator) with `select`: ```ts const selectNameEmailNotPosts = Prisma.validator()({ name: true, email: true, posts: false, }); ``` ### `include` `include` defines which relations are included in the result that Prisma Client returns. See: [Select fields and include relations](/orm/prisma-client/queries/select-fields) . #### Remarks - In [3.0.1](https://github.com/prisma/prisma/releases/3.0.1) and later, you can [`include` a `_count` of relations](#include-a-_count-of-relations) #### Examples ##### Include the `posts` and `profile` relation when loading `User` records ```ts const users = await prisma.user.findMany({ include: { posts: true, // Returns all fields for all posts profile: true, // Returns all Profile fields }, }); ``` ##### Include the `posts` relation on the returned objects when creating a new `User` record with two `Post` records ```ts const user = await prisma.user.create({ data: { email: 'alice@prisma.io', posts: { create: [{ title: 'This is my first post' }, { title: 'Here comes a second post' }], }, }, include: { posts: true }, // Returns all fields for all posts }); ``` #### Generated types for `include` The following example demonstrates how to use the [`validator`](/orm/prisma-client/type-safety/prisma-validator) with `include`: ```ts const includePosts = Prisma.validator()({ posts: true, }); ``` ##### Include a `_count` of relations ```ts const usersWithCount = await prisma.user.findMany({ include: { _count: { select: { posts: true }, }, }, }); ``` ```js no-copy { id: 1, name: "Bob", email: "bob@prisma.io", _count: { posts: 3 } }, { id: 2, name: "Enya", email: "enya@prisma.io", _count: { posts: 2 } } ``` ### `omit` `omit` defines which fields are excluded in the object that Prisma Client returns. #### Remarks - You cannot combine `omit` and `select` since they serve opposite purposes - `omit` was released into General Availability with Prisma ORM 6.2.0. It was available via the `omitApi` [Preview feature](/orm/reference/preview-features/client-preview-features) in Prisma ORM versions `5.13.0` through `6.1.0`. #### Examples ##### Omit the `password` field from all `User` records ```ts const result = await prisma.user.findMany({ omit: { password: true, }, }); ``` ```js no-copy [ { id: 1, email: 'jenny@prisma.io', name: 'Jenny', }, { id: 2, email: 'rose@prisma.io', name: 'Rose', }, ]; ``` ##### Omit the `title` fields from all `User`'s `posts` relation ```ts const results = await prisma.user.findMany({ omit: { password: true, }, include: { posts: { omit: { title: true, }, }, }, }); ``` ```js no-copy [ { id: 1, email: 'jenny@prisma.io', name: 'Jenny', posts: [ { id: 1, author: { id: 1, email: 'jenny@prisma.io', name: 'Jenny', }, authorId: 1, }, ], }, { id: 2, email: 'rose@prisma.io', name: 'Rose', posts: [ { id: 2, author: { id: 2, email: 'rose@prisma.io', name: 'Rose', }, authorId: 2, }, ], }, ]; ``` #### Generated types for `omit` The following example demonstrates how to use the [`validator`](/orm/prisma-client/type-safety/prisma-validator) with `omit`: ```ts const omitPassword = Prisma.validator()({ password: true, }); ``` ### `relationLoadStrategy` (Preview) `relationLoadStrategy` specifies how a relation should be loaded from the database. It has two possible values: - `join` (default): Uses a database-level `LATERAL JOIN` (PostgreSQL) or correlated subqueries (MySQL) and fetches all data with a single query to the database. - `query`: Sends multiple queries to the database (one per table) and joins them on the application level. > **Note**: Once `relationLoadStrategy` moves from [Preview](/orm/more/releases#preview) into [General Availability](/orm/more/releases/#generally-available-ga), `join` will universally become the default for all relation queries. You can learn more about join strategies [here](/orm/prisma-client/queries/relation-queries#relation-load-strategies-preview). Because the `relationLoadStrategy` option is currently in Preview, you need to enable it via the `relationJoins` preview feature flag in your Prisma schema file: ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["relationJoins"] } ``` After adding this flag, you need to run `prisma generate` again to re-generate Prisma Client. The `relationJoins` feature is currently available on PostgreSQL, CockroachDB and MySQL. #### Remarks - In most situations, the default `join` strategy will be more effective. Use `query` if you want to save resources on your database server or if you profiling shows that the application-level join is more performant. - You can only specify the `relationLoadStrategy` on the top-level in your query. The top-level choice will affect all nested sub-queries. #### Examples ##### Load the `posts` relation via a database-level JOIN when using `include` ```ts const users = await prisma.user.findMany({ relationLoadStrategy: 'join', include: { posts: true, }, }); ``` ##### Load the `posts` relation via a database-level JOIN when using `select` ```ts const users = await prisma.user.findMany({ relationLoadStrategy: 'join', select: { posts: true, }, }); ``` ### `where` `where` defines one or more [filters](#filter-conditions-and-operators), and can be used to filter on record properties (like a user's email address) or related record properties (like a user's top 10 most recent post titles). #### Examples ```ts const results = await prisma.user.findMany({ where: { email: { endsWith: 'prisma.io', }, }, }); ``` #### Generated types for `where` The following examples demonstrate how to use the [`validator`](/orm/prisma-client/type-safety/prisma-validator) with `where`: - `UserWhereInput` ```ts // UserWhereInput const whereNameIs = Prisma.validator()({ name: 'Rich', }); // It can be combined with conditional operators too const whereNameIs = Prisma.validator()({ name: 'Rich', AND: [ { email: { contains: 'rich@boop.com', }, }, ], }); ``` - `UserWhereUniqueInput` This type works by exposing any unique fields on the model. A field assigned `@id` is considered unique, as is one assigned `@unique`. From version 4.5.0, this type exposes all fields on the model. This means that when you filter for a single record based on a unique field, you can check additional non-unique and unique fields at the same time. [Learn more](#filter-on-non-unique-fields-with-userwhereuniqueinput). ```ts // UserWhereUniqueInput const whereEmailIsUnique = Prisma.validator()({ email: 'rich@boop.com', }) ``` - `PostScalarWhereInput` ```ts const whereScalarTitleIs = Prisma.validator()({ title: 'boop', }); ``` - `PostUpdateWithWhereUniqueWithoutAuthorInput` - This type accepts a unique `where` field (an `@id` or another assigned `@unique`) and updates any field on the `Post` model except the `Author`. The `Author` is the scalar field on the `Post` model. ```ts const updatePostByIdWithoutAuthor = Prisma.validator()({ where: { id: 1, }, data: { content: 'This is some updated content', published: true, title: 'This is a new title', }, }); ``` - `PostUpsertWithWhereUniqueWithoutAuthorInput` - This type will update the `Post` records title field where the id matches, if it doesn't exist it will create it instead. ```ts const updatePostTitleOrCreateIfNotExist = Prisma.validator()({ where: { id: 1, }, update: { title: 'This is a new title', }, create: { id: 1, title: 'If the title doesnt exist, then create one with this text', }, }); ``` - `PostUpdateManyWithWhereWithoutAuthorInput` - This type will update all `Post` records where published is set to false. ```ts const publishAllPosts = Prisma.validator()({ where: { published: { equals: false, }, }, data: { published: true, }, }); ``` ### `orderBy` Sorts a list of records. See also: [Sorting](/orm/prisma-client/queries/filtering-and-sorting) #### Remarks - In [2.16.0](https://github.com/prisma/prisma/releases/2.16.0) and later, you can [order by relation fields](#sort-post-by-the-related-user-records-name) - for example, order posts by the author's name. - In [3.5.0](https://github.com/prisma/prisma/releases/3.5.0) and later, in PostgreSQL you can [order by relevance](#sort-post-by-relevance-of-the-title). For details, see [Sort by relevance](/orm/prisma-client/queries/filtering-and-sorting#sort-by-relevance-postgresql-and-mysql). - In [4.1.0](https://github.com/prisma/prisma/releases/4.1.0) and later, you can [sort `null` records first or last](#sort-post-by-the-related-user-records-name-with-null-records-first). For details, see [Sort with nulls first or last](/orm/prisma-client/queries/filtering-and-sorting#sort-with-null-records-first-or-last). #### Inputs for `sort` argument | Name | Description | | ------ | ---------------------------- | | `asc` | Sort ascending (A → Z) | | `desc` | Sort descending (Z → A) | #### Inputs for `nulls` argument Note: - This argument is optional. - It is for use on optional [scalar](/orm/prisma-schema/data-model/models#scalar-fields) fields only. If you try to sort by nulls on a required or [relation](/orm/prisma-schema/data-model/models#relation-fields) field, Prisma Client throws a [P2009 error](/orm/reference/error-reference#p2009). - It is available in version 4.1.0 and later, as a preview feature. See [sort with nulls first or last](/orm/prisma-client/queries/filtering-and-sorting#sort-with-null-records-first-or-last) for details of how to enable the feature. | Name | Description | | ------- | ------------------------------ | | `first` | Sort with `null` values first. | | `last` | Sort with `null` values last. | #### Examples ##### Sort `User` by `email` field The following example returns all `User` records sorted by `email` ascending: ```ts const users = await prisma.user.findMany({ orderBy: { email: 'asc', }, }); ``` The following example returns all `User` records sorted by `email` descending: ```ts const users = await prisma.user.findMany({ orderBy: { email: 'desc', }, }); ``` #### Sort `Post` by the related `User` record's `name` The following query orders posts by user name: ```ts const posts = await prisma.post.findMany({ orderBy: { author: { name: 'asc', }, }, }); ``` #### Sort `Post` by the related `User` record's `name`, with `null` records first The following query orders posts by user name, with `null` records first: ```ts const posts = await prisma.post.findMany({ orderBy: { author: { name: { sort: 'asc', nulls: 'first' }, }, }, }); ``` #### Sort `Post` by relevance of the title :::info For PostgreSQL, this feature is still in Preview. [Enable the `fullTextSearchPostgres` feature flag](/orm/prisma-client/queries/full-text-search#enabling-full-text-search-for-postgresql) in order to use it. ::: The following query orders posts by relevance of the search term `'database'` to the title: ```ts const posts = await prisma.post.findMany({ orderBy: { _relevance: { fields: ['title'], search: 'database', sort: 'asc' }, }) ``` #### Sort `User` by the `posts` count The following query orders users by post count: ```ts const getActiveusers = await prisma.user.findMany({ orderBy: { posts: { count: 'desc', }, }, }); ``` ##### Sort `User` by multiple fields - `email` _and_ `role` The following example sorts users by two fields - first `email`, then `role`: ```ts const users = await prisma.user.findMany({ select: { email: true, role: true, }, orderBy: [ { email: 'desc', }, { role: 'desc', }, ], }); ``` ```json no-copy [ { "email": "yuki@prisma.io", "role": "USER" }, { "email": "nora@prisma.io", "role": "USER" }, { "email": "mary@prisma.io", "role": "MODERATOR" }, { "email": "elsa@prisma.io", "role": "MODERATOR" }, { "email": "eloise@prisma.io", "role": "USER" }, { "email": "coco@prisma.io", "role": "ADMIN" }, { "email": "anna@prisma.io", "role": "USER" }, { "email": "alice@prisma.io", "role": "USER" } ] ``` The order of sorting parameters matters - the following query sorts by `role`, then `email`. Not the difference in the results: ```ts const users = await prisma.user.findMany({ select: { email: true, role: true, }, orderBy: [ { role: 'desc', }, { email: 'desc', }, ], }); ``` ```json no-copy [ { "email": "mary@prisma.io", "role": "MODERATOR" }, { "email": "elsa@prisma.io", "role": "MODERATOR" }, { "email": "yuki@prisma.io", "role": "USER" }, { "email": "nora@prisma.io", "role": "USER" }, { "email": "eloise@prisma.io", "role": "USER" }, { "email": "anna@prisma.io", "role": "USER" }, { "email": "alice@prisma.io", "role": "USER" }, { "email": "coco@prisma.io", "role": "ADMIN" } ] ``` ##### Sort `User` by `email`, select `name` and `email` The following example returns all the `name` and `email` fields of all `User` records, sorted by `email`: ```ts const users3 = await prisma.user.findMany({ orderBy: { email: 'asc', }, select: { name: true, email: true, }, }); ``` ```js no-copy [ { name: 'Alice', email: 'alice@prisma.io', }, { name: 'Ariadne', email: 'ariadne@prisma.io', }, { name: 'Bob', email: 'bob@prisma.io', }, ]; ``` ##### Sort `User` records by `email` and sort nested `Post` records by `title` The following example: - Returns all `User` records sorted by `email` - For each `User` record, returns the `title` field of all nested `Post` records sorted by `title` ```ts const usersWithPosts = await prisma.user.findMany({ orderBy: { email: 'asc', }, include: { posts: { select: { title: true, }, orderBy: { title: 'asc', }, }, }, }); ``` ```json no-copy [ { "id": 2, "email": "alice@prisma.io", "name": "Alice", "posts": [ { "title": "Watch the talks from Prisma Day 2019" } ] }, { "id": 3, "email": "ariadne@prisma.io", "name": "Ariadne", "posts": [ { "title": "How to connect to a SQLite database" }, { "title": "My first day at Prisma" } ] }, { "id": 1, "email": "bob@prisma.io", "name": "Bob", "posts": [ { "title": "Follow Prisma on Twitter" }, { "title": "Subscribe to GraphQL Weekly for community news " } ] } ] ``` ##### Sort one user's nested list of `Post` records The following example retrieves a single `User` record by ID, as well as a list of nested `Post` records sorted by `title`: ```ts const userWithPosts = await prisma.user.findUnique({ where: { id: 1, }, include: { posts: { orderBy: { title: 'desc', }, select: { title: true, published: true, }, }, }, }); ``` ```json no-copy { "email": "sarah@prisma.io", "id": 1, "name": "Sarah", "extendedProfile": null, "role": "USER", "posts": [ { "title": "Prisma Day 2020", "published": false }, { "title": "My first post", "published": false }, { "title": "All about databases", "published": true } ] } ``` ##### Sort by `enum` The following sorts all `User` records by `role` (an `enum`): ```ts const sort = await prisma.user.findMany({ orderBy: { role: 'desc', }, select: { email: true, role: true, }, }); ``` ```json no-copy [ { "email": "emma@prisma.io", "role": "USER" }, { "email": "suma@prisma.io", "role": "ADMIN" }, { "email": "kwame@prisma.io", "role": "ADMIN" }, { "email": "pearl@prisma.io", "role": "ADMIN" } ] ``` #### Generated types for `orderBy` The following examples demonstrate how to use the [`validator`](/orm/prisma-client/type-safety/prisma-validator) with `orderBy`: - `UserOrderByInput` ```ts const orderEmailsByDescending = Prisma.validator()({ email: 'desc', }); ``` ### `distinct` Deduplicate a list of records from [`findMany`](#findmany) or [`findFirst`](#findfirst). See also: [Aggregation, grouping, and summarizing](/orm/prisma-client/queries/aggregation-grouping-summarizing#select-distinct) #### Examples ##### Select distinct on a single field The following example returns all distinct `city` fields, and selects only the `city` and `country` fields: ```ts const distinctCities = await prisma.user.findMany({ select: { city: true, country: true, }, distinct: ['city'], }); ``` ```js no-lines no-copy [ { city: 'Paris', country: 'France' }, { city: 'Lyon', country: 'France' }, ]; ``` ##### Select distinct on multiple fields The following example returns all distinct `city` _and_ `country` field combinations, and selects only the `city` and `country` fields: ```ts const distinctCitiesAndCountries = await prisma.user.findMany({ select: { city: true, country: true, }, distinct: ['city', 'country'], }); ``` ```js no-lines no-copy [ { city: 'Paris', country: 'France' }, { city: 'Paris', country: 'Denmark' }, { city: 'Lyon', country: 'France' }, ]; ``` Note that there is now a "Paris, Denmark" in addition to "Paris, France": ##### Select distinct in combination with a filter The following example returns all distinct `city` _and_ `country` field combinations where the user's email contains `"prisma.io"`, and selects only the `city` and `country` fields: ```ts const distinctCitiesAndCountries = await prisma.user.findMany({ where: { email: { contains: 'prisma.io', }, }, select: { city: true, country: true, }, distinct: ['city', 'country'], }); ``` ```js no-copy [ { city: 'Paris', country: 'Denmark' }, { city: 'Lyon', country: 'France' }, ]; ``` ## `nativeDistinct` Enabling `nativeDistinct` in your Prisma schema pushes the `distinct` operation to the database layer (where supported). This can significantly improve performance. However, note that: - Some databases may not fully support DISTINCT on certain field combinations. - Behavior can differ among providers. To enable `nativeDistinct`: ```prisma showLineNumbers generator client { provider = "prisma-client-js" previewFeatures = ["nativeDistinct"] } ``` See [Preview Features](/orm/reference/preview-features/client-preview-features#preview-features-promoted-to-general-availability) for more details. ## Nested queries ### `create` A nested `create` query adds a new related record or set of records to a parent record. See: [Working with relations](/orm/prisma-client/queries/relation-queries) #### Remarks - `create` is available as a nested query when you `create()` (`prisma.user.create(...)`) a new parent record or `update()` (`prisma.user.update(...)`) an existing parent record. - You can use a nested `create` _or_ a nested [`createMany`](#createmany-1) to create multiple related records. If you require the [`skipDuplicates` query option](#nested-createmany-options) you should use `createMany`. #### Examples ##### Create a new `User` record with a new `Profile` record ```ts highlight=5;normal const user = await prisma.user.create({ data: { email: 'alice@prisma.io', profile: { create: { bio: 'Hello World' }, }, }, }); ``` ##### Create a new `Profile` record with a new `User` record ```ts const user = await prisma.profile.create({ data: { bio: 'Hello World', user: { //highlight-next-line create: { email: 'alice@prisma.io' }, }, }, }) ``` ##### Create a new `User` record with a new `Post` record ```ts highlight=5;normal const user = await prisma.user.create({ data: { email: 'alice@prisma.io', posts: { create: { title: 'Hello World' }, }, }, }); ``` ##### Create a new `User` record with two new `Post` records Because it's a one-to-many relation, you can also create multiple `Post` records at once by passing an array to `create`: ```ts highlight=5-12;normal const user = await prisma.user.create({ data: { email: 'alice@prisma.io', posts: { create: [ { title: 'This is my first post', }, { title: 'Here comes a second post', }, ], }, }, }); ``` Note: You can also use a nested [`createMany`](#createmany-1) to achieve the same result. ##### Update an existing `User` record by creating a new `Profile` record ```ts highlight=5;normal; const user = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { profile: { create: { bio: 'Hello World' }, }, }, }); ``` ##### Update an existing `User` record by creating a new `Post` record ```ts const user = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { posts: { //highlight-next-line create: { title: 'Hello World' }, }, }, }) ``` ### `createMany` A nested `createMany` query adds a new set of records to a parent record. See: [Working with relations](/orm/prisma-client/queries/relation-queries) #### Remarks - `createMany` is available as a nested query when you `create()` (`prisma.user.create(...)`) a new parent record or `update()` (`prisma.user.update(...)`) an existing parent record. - Available in the context of a one-to-many relation — for example, you can `prisma.user.create(...)` a user and use a nested `createMany` to create multiple posts (posts have one user). - **Not** available in the context of a many-to-many relation — for example, you **cannot** `prisma.post.create(...)` a post and use a nested `createMany` to create categories (many posts have many categories). - You cannot nest an additional `create` or `createMany`. - Allows setting foreign keys directly — for example, setting the `categoryId` on a post. - As of Prisma ORM version 5.12.0, nested `createMany` is supported by SQLite. - You can use a nested `create` _or_ a nested `createMany` to create multiple related records - [if you do not need the `skipDuplicates` query option, you should probably use `create`](/orm/prisma-client/queries/relation-queries#create-a-single-record-and-multiple-related-records). #### Options \{#nested-createmany-options} | Name | Type | Required | Description | | ----------------- | --------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `data` | `Enumerable` | **Yes** | Wraps all the model fields in a type so that they can be provided when creating new records. Fields that are marked as optional or have default values in the datamodel are optional. | | `skipDuplicates?` | `boolean` | No | Do not insert records with unique fields or ID fields that already exist. Only supported by databases that support [`ON CONFLICT DO NOTHING`](https://www.postgresql.org/docs/9.5/sql-insert.html#SQL-ON-CONFLICT). This excludes MongoDB and SQLServer | #### Examples ##### Update a `User` and multiple new related `Post` records ```ts const user = await prisma.user.update({ where: { id: 9, }, data: { name: 'Elliott', posts: { createMany: { data: [{ title: 'My first post' }, { title: 'My second post' }], }, }, }, }); ``` ### `set` `set` overwrites the value of a relation - for example, replacing a list of `Post` records with a different list. See: [Working with relations](/orm/prisma-client/queries/relation-queries) #### Examples ##### Update an existing `User` record by disconnecting any previous `Post` records and connecting two other existing ones ```ts const user = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { posts: { set: [{ id: 32 }, { id: 42 }], }, }, }); ``` ### `connect` A nested `connect` query connects a record to an existing related record by specifying an ID or unique identifier. See: [Working with relations](/orm/prisma-client/queries/relation-queries) #### Remarks - `connect` is available as a nested query when you create a new parent record or update an existing parent record. - If the related record does not exist, Prisma Client throws an exception: ``` The required connected records were not found. Expected 1 records to be connected, found 0. ``` - When using `set` and `connect` together, the order in which they are applied significantly impacts the result. If `set` is used before `connect`, the connected records will only reflect the final state established by the `connect` operation, as `set` clears all existing connections before `connect` establishes new ones. Conversely, if `connect` is applied before `set`, the `set` operation will override the `connect` action by clearing all connected records and replacing them with its own specified state. #### Examples ##### Create a new `Profile` record and connect it to an existing `User` record via unique field ```ts const user = await prisma.profile.create({ data: { bio: 'Hello World', user: { connect: { email: 'alice@prisma.io' }, }, }, }); ``` ##### Create a new `Profile` record and connect it to an existing `User` record via an ID field ```ts const user = await prisma.profile.create({ data: { bio: 'Hello World', user: { connect: { id: 42 }, // sets userId of Profile record }, }, }); ``` In [2.11.0](https://github.com/prisma/prisma/releases/2.11.0) and later, you can set the foreign key directly: ```ts const user = await prisma.profile.create({ data: { bio: 'Hello World', userId: 42, }, }); ``` However, you can't use both the direct approach and the `connect` approach in the same query. See [this issue comment](https://github.com/prisma/prisma/issues/4322#issuecomment-737976117) for details. ##### Create a new `Post` record and connect it to an existing `User` record ```ts const user = await prisma.post.create({ data: { title: 'Hello World', author: { connect: { email: 'alice@prisma.io' }, }, }, }); ``` ##### Update an existing `User` record by connecting it to an existing `Profile` record ```ts const user = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { profile: { connect: { id: 24 }, }, }, }); ``` ##### Update an existing `User` record by connecting it to two existing `Post` records ```ts const user = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { posts: { connect: [{ id: 24 }, { id: 42 }], }, }, }); ``` ### `connectOrCreate` `connectOrCreate` _either_ connects a record to an existing related record by ID or unique identifier _or_ creates a new related record if the record does not exist. See: [Working with relations](/orm/prisma-client/queries/relation-queries) #### Remarks - Multiple `connectOrCreate` queries that run _as concurrent transactions_ can result in a **race condition**. Consider the following example, where two queries attempt to `connectOrCreate` a blog post tag named `computing` at the same time (tag names must be unique): ```ts const createPost = await prisma.post.create({ data: { title: 'How to create a compiler', content: '...', author: { connect: { id: 9, }, }, tags: { connectOrCreate: { create: { name: 'computing', }, where: { name: 'computing', }, }, }, }, }) ``` ```ts const createPost = await prisma.post.create({ data: { title: 'How to handle schema drift in production', content: '...', author: { connect: { id: 15, }, }, tags: { connectOrCreate: { create: { name: 'computing', }, where: { name: 'computing', }, }, }, }, }) ``` If query A and query B overlap in the following way, query A results in an exception: | Query A (Fail ❌) | Query B (Success ✅) | | :--------------------------------------------------------------- | :--------------------------------------------------------------- | | Query hits server, starts transaction A | Query hits server, starts transaction B | | | Find record where `tagName` equals `computing`, record not found | | Find record where `tagName` equals `computing`, record not found | | | | Create record where `tagName` equals `computing` and connect | | Create record where `tagName` equals `computing` | | | Unique violation, record already created by transaction B | | To work around this scenario, we recommend catching the unique violation exception (`PrismaClientKnownRequestError`, error `P2002`) and retrying failed queries. #### Examples ##### Create a new `Profile` record, then connect it to an existing `User` record _or_ create a new `User` The following example: 1. Creates a `Profile` 2. Attempts to connect the profile to a `User` where the email address is `alice@prisma.io` 3. Creates a new user if a matching user does not exist ```ts const user = await prisma.profile.create({ data: { bio: 'The coolest Alice on the planet', user: { connectOrCreate: { where: { email: 'alice@prisma.io' }, create: { email: 'alice@prisma.io'} }, }, }) ``` ##### Create a new `Post` record and connect it to an existing `User` record, _or_ create a new `User` ```ts const user = await prisma.post.create({ data: { title: 'Hello World', author: { connectOrCreate: { where: { email: 'alice@prisma.io' }, create: { email: 'alice@prisma.io' }, }, }, }, }); ``` ##### Update an existing `User` record by connecting it to an existing `Profile` record, _or_ creating a new `Profile` record The following example: 1. Attempts to connect the user to a `Profile` with an `id` of `20` 2. Creates a new profile if a matching profile does not exist ```ts const updateUser = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { profile: { connectOrCreate: { where: { id: 20 }, create: { bio: 'The coolest Alice in town', }, }, }, }, }); ``` ##### Update an existing `User` record by connect it to two existing `Post` records, or creating two new `Post` records ```ts const user = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { posts: { connectOrCreate: [ { where: { id: 32 }, create: { title: 'This is my first post' }, }, { where: { id: 19 }, create: { title: 'This is my second post' }, }, ], }, }, }); ``` ### `disconnect` A nested `disconnect` query breaks the connection between a parent record and a related record, but does not delete either record. See: [Working with relations](/orm/prisma-client/queries/relation-queries) #### Remarks - `disconnect` is only available if the relation is optional. - If the relationship you are attempting to disconnect does not exist: - ([In 2.21.0 and later](https://github.com/prisma/prisma/releases/tag/2.21.0)), the operation does nothing - (Before [2.21.0](https://github.com/prisma/prisma/releases/tag/2.21.0)) Prisma Client throws an exception if the provided ID or unique identifier is not connected: ``` The records for relation `PostToUser` between the `User` and `Post` models are not connected. ``` #### Examples ##### Update an existing `User` record by disconnecting the `Profile` record it's connected to ```ts const user = await prisma.user.update({ where: { email: 'bob@prisma.io' }, data: { profile: { disconnect: true, }, }, }); ``` ##### Update an existing `User` record by disconnecting two `Post` records it's connected to ```ts const user = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { posts: { disconnect: [{ id: 44 }, { id: 46 }], }, }, }); ``` ### `update` A nested `update` query updates one or more related records where the parent record's ID is `n`. See: [Working with relations](/orm/prisma-client/queries/relation-queries#update-a-specific-related-record) #### Remarks - Nested `update` queries are only available in the context of a top-level `update` query (for example, `prisma.user.update(...)`). - If the parent record does not exist, Prisma Client throws an exception: ``` AssertionError("Expected a valid parent ID to be present for nested update to-one case.") ``` - If the related record that you want to update does not exist, Prisma Client throws an exception: ``` AssertionError("Expected a valid parent ID to be present for nested update to-one case.") ``` #### Examples ##### Update an existing `User` record by updating the `Profile` record it's connected to ```ts const user = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { profile: { update: { bio: 'Hello World' }, }, }, }); ``` ##### Update an existing `User` record by updating two `Post` records it's connected to ```ts const user = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { posts: { update: [ { data: { published: true }, where: { id: 32 }, }, { data: { published: true }, where: { id: 23 }, }, ], }, }, }); ``` ### `upsert` This section covers the usage of nested upsert within `update()`. To learn about the [`upsert()`](#upsert) operation, reference the linked documentation. A nested `upsert` query updates a related record if it exists, or creates a new related record. #### Examples ##### Update an existing `User` record by updating the `Profile` record it's connected to or creating a new one (_upsert_) ```ts const user = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { profile: { upsert: { create: { bio: 'Hello World' }, update: { bio: 'Hello World' }, }, }, }, }); ``` ##### Update an existing `User` record by updating two `Post` record it's connected to or creating new ones (_upsert_) ```ts const user = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { posts: { upsert: [ { create: { title: 'This is my first post' }, update: { title: 'This is my first post' }, where: { id: 32 }, }, { create: { title: 'This is my second post' }, update: { title: 'This is my second post' }, where: { id: 23 }, }, ], }, }, }); ``` ### `delete` A nested `delete` query deletes a related record. The parent record is not deleted. #### Remarks - `delete` is only available if the relation is optional. #### Examples ##### Update an existing `User` record by deleting the `Profile` record it's connected to ```ts const user = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { profile: { delete: true, }, }, }); ``` ##### Update an existing `User` record by deleting two `Post` records it's connected to ```ts const user = await prisma.user.update({ where: { email: 'alice@prisma.io' }, data: { posts: { delete: [{ id: 34 }, { id: 36 }], }, }, }); ``` ### `updateMany` A nested `updateMany` updates a list of related records and supports filtering - for example, you can update a user's unpublished posts. #### Examples ##### Update all unpublished posts belonging to a specific user ```ts const result = await prisma.user.update({ where: { id: 2, }, data: { posts: { updateMany: { where: { published: false, }, data: { likes: 0, }, }, }, }, }); ``` ### `deleteMany` A nested `deleteMany` deletes related records and supports filtering. For example, you can delete a user's posts while updating other properties of that user. #### Examples ##### Delete all posts belonging to a specific user as part of an update ```ts const result = await prisma.user.update({ where: { id: 2, }, data: { name: 'Updated name', posts: { deleteMany: {}, }, }, }); ``` ## Filter conditions and operators ### `equals` Value equals `n`. #### Examples **Return all users where `name` equals `"Eleanor"`** ```ts const result = await prisma.user.findMany({ where: { name: { equals: 'Eleanor', }, }, }); ``` You can also exclude the `equals`: ```ts const result = await prisma.user.findMany({ where: { name: 'Eleanor', }, }); ``` **Return all products with a quantity lower than the "warn quantity" threshold** This example compares fields of the same model which is available as of version 4.3.0. ```ts const productsWithLowQuantity = await prisma.product.findMany({ where: { quantity: { lte: prisma.product.fields.warnQuantity }, }, }); ``` **Return all users that have blue and green as their favorite colors** This example finds users that have set their `favoriteColors` field to `['blue', 'green']`. Note that when using `equals`, order of elements matters. That is to say `['blue', 'green']` is **not** equal to `['green', 'blue']` ```ts const favoriteColorFriends = await prisma.user.findMany({ where: { favoriteColors: { equals: ['blue', 'green'], }, }, }); ``` ### `not` Value does not equal `n`. #### Examples ##### Return all users where `name` does **not** equal `"Eleanor"` ```ts const result = await prisma.user.findMany({ where: { name: { not: 'Eleanor', }, }, }); ``` :::warning `not` will return all items that do not match a given value. However, if the column is nullable, `NULL` values will not be returned. If you require null values to be returned, use an [`OR`](#or) operator to include `NULL` values. ::: ##### Return all users where `name` does **not** equal `"Eleanor"` **including** users where `name` is `NULL` ```ts await prisma.user.findMany({ where: { OR: [ { name: { not: 'Eleanor' } }, { name: null } ] } }) ``` ### `in` Value `n` exists in list. :::note `null` values are not returned. For example, if you combine `in` and `NOT` to return a user whose name is _not_ in the list, users with `null` value names are not returned. ::: #### Examples ##### Get `User` records where the `id` can be found in the following list: `[22, 91, 14, 2, 5]` ```ts const getUser = await prisma.user.findMany({ where: { id: { in: [22, 91, 14, 2, 5] }, }, }); ``` ##### Get `User` records where the `name` can be found in the following list: `['Saqui', 'Clementine', 'Bob']` ```ts const getUser = await prisma.user.findMany({ where: { name: { in: ['Saqui', 'Clementine', 'Bob'] }, }, }); ``` ##### Get `User` records where `name` is **not** present in the list The following example combines `in` and [`NOT`](#not). You can also use [`notIn`](#notin). ```ts const getUser = await prisma.user.findMany({ where: { NOT: { name: { in: ['Saqui', 'Clementine', 'Bob'] }, }, }, }); ``` ##### Get a `User` record where at least one `Post` has at least one specified `Category` ```ts const getUser = await prisma.user.findMany({ where: { // Find users where.. posts: { some: { // ..at least one (some) posts.. categories: { some: { // .. have at least one category .. name: { in: ['Food', 'Introductions'], // .. with a name that matches one of the following. }, }, }, }, }, }, }); ``` ### `notIn` Value `n` does not exist in list. #### Remarks - `null` values are not returned. #### Examples ##### Get `User` records where the `id` can **not** be found in the following list: `[22, 91, 14, 2, 5]` ```ts const getUser = await prisma.user.findMany({ where: { id: { notIn: [22, 91, 14, 2, 5] }, }, }); ``` ### `lt` Value `n` is less than `x`. #### Examples ##### Get all `Post` records where `likes` is less than `9` ```ts const getPosts = await prisma.post.findMany({ where: { likes: { lt: 9, }, }, }); ``` ### `lte` Value `n` is less than _or_ equal to `x`. #### Examples ##### Get all `Post` records where `likes` is less or equal to `9` ```ts const getPosts = await prisma.post.findMany({ where: { likes: { lte: 9, }, }, }); ``` ### `gt` Value `n` is greater than `x`. #### Examples ##### Get all `Post` records where `likes` is greater than `9` ```ts const getPosts = await prisma.post.findMany({ where: { likes: { gt: 9, }, }, }); ``` ### `gte` Value `n` is greater than _or_ equal to `x`. #### Examples ##### Get all `Post` records where `likes` is greater than or equal to `9` ```ts const getPosts = await prisma.post.findMany({ where: { likes: { gte: 9, }, }, }); ``` #### Examples ##### Get all `Post` records where `date_created` is greater than March 19th, 2020 ```js const result = await prisma.post.findMany({ where: { date_created: { gte: new Date('2020-03-19T14:21:00+0200') /* Includes time offset for UTC */, }, }, }); ``` ### `contains` Value `n` contains `x`. #### Examples ##### Count all `Post` records where `content` contains `databases` ```js const result = await prisma.post.count({ where: { content: { contains: 'databases', }, }, }); ``` ##### Count all `Post` records where `content` **does not** contain `databases` ```js const result = await prisma.post.count({ where: { NOT: { content: { contains: 'databases', }, }, }, }); ``` ### `search` Use [Full-Text Search](/orm/prisma-client/queries/full-text-search) to search within a `String` field. :::info For PostgreSQL, this feature is still in Preview. [Enable the `fullTextSearchPostgres` feature flag](/orm/prisma-client/queries/full-text-search#enabling-full-text-search-for-postgresql) in order to use it. ::: #### Examples ##### Find all posts with a title that contains `cat` or `dog`. ```js const result = await prisma.post.findMany({ where: { title: { search: 'cat | dog', }, }, }); ``` ##### Find all posts with a title that contains `cat` and `dog`. ```js const result = await prisma.post.findMany({ where: { title: { search: 'cat & dog', }, }, }); ``` ##### Find all posts with a title that doesn't contain `cat`. ```js const result = await prisma.post.findMany({ where: { title: { search: '!cat', }, }, }); ``` ### `mode` #### Remarks - Supported by the PostgreSQL and MongoDB connectors only #### Examples ##### Get all `Post` records where `title` contains `prisma`, in a case insensitive way ```js const result = await prisma.post.findMany({ where: { title: { contains: 'prisma', mode: 'insensitive', }, }, }); ``` ### `startsWith` #### Examples ##### Get all `Post` records where `title` starts with `Pr` (such as `Prisma`) ```js const result = await prisma.post.findMany({ where: { title: { startsWith: 'Pr', }, }, }); ``` ### `endsWith` #### Get all `User` records where `email` ends with `prisma.io` ```js const result = await prisma.user.findMany({ where: { email: { endsWith: 'prisma.io', }, }, }); ``` ### `AND` All conditions must return `true`. Alternatively, pass a list of objects into the `where` clause - the [`AND` operator is not required](#get-all-post-records-where-the-content-field-contains-prisma-and-published-is-false-no-and). #### Examples ##### Get all `Post` records where the `content` field contains `Prisma` and `published` is `false` ```js const result = await prisma.post.findMany({ where: { AND: [ { content: { contains: 'Prisma', }, }, { published: { equals: false, }, }, ], }, }); ``` ##### Get all `Post` records where the `content` field contains `Prisma` and `published` is `false` (no `AND`) The following format returns the same results as the previous example **without** the `AND` operator: ```js const result = await prisma.post.findMany({ where: { content: { contains: 'Prisma', }, published: { equals: false, }, }, }); ``` ##### Get all `Post` records where the `title` field contains `Prisma` or `databases`, and `published` is `false` The following example combines `OR` and `AND`: ```js const result = await prisma.post.findMany({ where: { OR: [ { title: { contains: 'Prisma', }, }, { title: { contains: 'databases', }, }, ], AND: { published: false, }, }, }); ``` ### `OR` One or more conditions must return `true`. #### Examples ##### Get all `Post` records where the `title` field contains `Prisma` or `databases` ```js const result = await prisma.post.findMany({ where: { OR: [ { title: { contains: 'Prisma', }, }, { title: { contains: 'databases', }, }, ], }, }); ``` ##### Get all `Post` records where the `title` field contains `Prisma` or `databases`, but not `SQL` The following example combines `OR` and `NOT`: ```js const result = await prisma.post.findMany({ where: { OR: [ { title: { contains: 'Prisma', }, }, { title: { contains: 'databases', }, }, ], NOT: { title: { contains: 'SQL', }, }, }, }); ``` ##### Get all `Post` records where the `title` field contains `Prisma` or `databases`, and `published` is `false` The following example combines `OR` and `AND`: ```js const result = await prisma.post.findMany({ where: { OR: [ { title: { contains: 'Prisma', }, }, { title: { contains: 'databases', }, }, ], AND: { published: false, }, }, }); ``` ### `NOT` All conditions must return `false`. #### Examples ##### Get all `Post` records where the `title` does not contain `SQL` ```js const result = await prisma.post.findMany({ where: { NOT: { title: { contains: 'SQL', }, }, }, }); ``` ##### Get all `Post` records where the `title` field contains `Prisma` or `databases`, but not `SQL`, and the related `User` record' email address does not contain `sarah` ```js const result = await prisma.post.findMany({ where: { OR: [ { title: { contains: 'Prisma', }, }, { title: { contains: 'databases', }, }, ], NOT: { title: { contains: 'SQL', }, }, user: { NOT: { email: { contains: 'sarah', }, }, }, }, include: { user: true, }, }); ``` ## Relation filters ### `some` Returns all records where **one or more** ("some") _related_ records match filtering criteria. #### Remarks - You can use `some` without parameters to return all records with at least one relation #### Examples ##### Get all `User` records where _some_ posts mention `Prisma` ```ts const result = await prisma.user.findMany({ where: { post: { some: { content: { contains: "Prisma" } } } } } ``` ### `every` Returns all records where **all** ("every") _related_ records match filtering criteria. #### Examples ##### Get all `User` records where _all_ posts are published ```ts const result = await prisma.user.findMany({ where: { post: { every: { published: true }, } } } ``` ### `none` Returns all records where **zero** _related_ records match filtering criteria. #### Remarks - You can use `none` without parameters to [return all records with no relations](#get-all-user-records-with-zero-posts) #### Examples ##### Get all `User` records with zero posts ```ts const result = await prisma.user.findMany({ where: { post: { none: {} // User has no posts } } } ``` ##### Get all `User` records with zero published posts ```ts const result = await prisma.user.findMany({ where: { post: { none: { published: true } } } } ``` ### `is` Returns all records where related record matches filtering criteria (for example, user's name `is` Bob). #### Examples ##### Get all `Post` records where user's name is `"Bob"` ```ts const result = await prisma.post.findMany({ where: { user: { is: { name: "Bob" }, } } } ``` ### `isNot` Returns all records where the related record does not match the filtering criteria (for example, user's name `isNot` Bob). #### Examples ##### Get all `Post` records where user's name is NOT `"Bob"` ```ts const result = await prisma.post.findMany({ where: { user: { isNot: { name: "Bob" }, } } } ``` ## Scalar list methods ### `set` Use `set` to overwrite the value of a scalar list field. #### Remarks - `set` is optional - you can set the value directly: ```ts tags: ['computers', 'books']; ``` #### Examples ##### Set the value of `tags` to a list of string values ```ts const setTags = await prisma.post.update({ where: { id: 9, }, data: { tags: { set: ['computing', 'books'], }, }, }); ``` ##### Set `tags` to a list of values _without_ using the `set` keyword ```ts const setTags = await prisma.post.update({ where: { id: 9, }, data: { tags: ['computing', 'books'], }, }); ``` #### Set the value of `tags` to a single string value ```ts const setTags = await prisma.post.update({ where: { id: 9, }, data: { tags: { set: 'computing', }, }, }); ``` ### `push` `push` is available in version [2.20.0](https://github.com/prisma/prisma/releases/2.20.0) and later. Use `push` to add _one_ value or _multiple_ values to a scalar list field. #### Remarks - Available for PostgreSQL and MongoDB only. - You can push a list of values or only a single value. #### Examples ##### Add a `computing` item to the `tags` list ```ts const addTag = await prisma.post.update({ where: { id: 9, }, data: { tags: { push: 'computing', }, }, }); ``` ```ts const addTag = await prisma.post.update({ where: { id: 9, }, data: { tags: { push: ['computing', 'genetics'], }, }, }); ``` ### `unset` This method is available on MongoDB only in versions [3.11.1](https://github.com/prisma/prisma/releases/tag/3.11.1) and later. Use `unset` to unset the value of a scalar list. Unlike `set: null`, `unset` removes the list entirely. #### Examples ##### Unset the value of `tags` ```ts const setTags = await prisma.post.update({ where: { id: 9, }, data: { tags: { unset: true, }, }, }); ``` ## Scalar list filters Scalar list filters allow you to filter by the contents of a list / array field. Available for: - PostgreSQL in versions [2.15.0](https://github.com/prisma/prisma/releases/tag/2.15.0) and later - CockroachDB in versions [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0) and later - MongoDB in versions [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0) and later ### Remarks - Scalar list / array filters [ignore `NULL` values](/orm/prisma-client/special-fields-and-types/working-with-scalar-lists-arrays#null-values-in-arrays) . Using `isEmpty` or `NOT` does not return records with `NULL` value lists / arrays, and `{ equals: null }` results in an error. ### `has` The given value exists in the list. #### Examples The following query returns all `Post` records where the `tags` list includes `"databases"`: ```ts const posts = await client.post.findMany({ where: { tags: { has: 'databases', }, }, }); ``` The following query returns all `Post` records where the `tags` list **does not** include `"databases"`: ```ts const posts = await client.post.findMany({ where: { NOT: { tags: { has: 'databases', }, }, }, }); ``` ### `hasEvery` Every value exists in the list. #### Examples The following query returns all `Post` records where the `tags` list includes _at least_ `"databases"` _and_ `"typescript"`: ```ts const posts = await prisma.post.findMany({ where: { tags: { hasEvery: ['databases', 'typescript'], }, }, }); ``` ### `hasSome` At least one value exists in the list. #### Examples The following query returns all `Post` records where the `tags` list includes `"databases"` _or_ `"typescript"`: ```ts const posts = await prisma.post.findMany({ where: { tags: { hasSome: ['databases', 'typescript'], }, }, }); ``` ### `isEmpty` The list is empty. #### Examples The following query returns all `Post` records that have no tags: ```ts const posts = await prisma.post.findMany({ where: { tags: { isEmpty: true, }, }, }); ``` ### `isSet` This filter is available on MongoDB only in versions [3.11.1](https://github.com/prisma/prisma/releases/tag/3.11.1) and later. Filter lists to include only results that have been set (either set to a value, or explicitly set to `null`). Setting this filter to `true` will exclude undefined results that are not set at all. #### Examples The following query returns all `Post` records where the `tags` have been set to either `null` or a value: ```ts const posts = await prisma.post.findMany({ where: { tags: { isSet: true, }, }, }); ``` ### `equals` The list matches the given value exactly. #### Examples The following query returns all `Post` records where the `tags` list includes `"databases"` and `"typescript"` only: ```ts const posts = await prisma.post.findMany({ where: { tags: { equals: ['databases', 'typescript'], }, }, }); ``` ## Composite type methods Available for MongoDB only in Prisma `3.10.0` and later. Composite type methods allow you to create, update and delete [composite types](/orm/prisma-client/special-fields-and-types/composite-types). ### `set` Use `set` to overwrite the value of a composite type. #### Remarks - The `set` keyword is optional - you can set the value directly: ```ts photos: [ { height: 100, width: 200, url: '1.jpg' }, { height: 100, width: 200, url: '2.jpg' }, ]; ``` #### Examples ##### Set the `shippingAddress` composite type within a new `order` ```ts const order = await prisma.order.create({ data: { // Normal relation product: { connect: { id: 'some-object-id' } }, color: 'Red', size: 'Large', // Composite type shippingAddress: { set: { street: '1084 Candycane Lane', city: 'Silverlake', zip: '84323', }, }, }, }); ``` ##### Set an optional composite type to `null` ```ts const order = await prisma.order.create({ data: { // Embedded optional type, set to null billingAddress: { set: null, }, }, }); ``` ### `unset` Use `unset` to unset the value of a composite type. Unlike `set: null`, this removes the field entirely from the MongoDB document. #### Examples ##### Remove the `billingAddress` from an `order` ```ts const order = await prisma.order.update({ where: { id: 'some-object-id', }, data: { billingAddress: { // Unset the billing address // Removes "billingAddress" field from order unset: true, }, }, }); ``` ### `update` Use `update` to update fields within a required composite type. #### Remarks The `update` method cannot be used on optional types. Instead, use [upsert](#upsert-2) #### Examples ##### Update the zip field of a `shippingAddress` composite type ```ts const order = await prisma.order.update({ where: { id: 'some-object-id', }, data: { shippingAddress: { // Update just the zip field update: { zip: '41232', }, }, }, }); ``` ### `upsert` Use `upsert` to update an existing optional composite type if it exists, and otherwise set the composite type. #### Remarks The `upsert` method cannot be used on required types. Instead, use [update](#update-2) #### Examples ##### Create a new `billingAddress` if it doesn't exist, and otherwise update it ```ts const order = await prisma.order.update({ where: { id: 'some-object-id', }, data: { billingAddress: { // Create the address if it doesn't exist, // otherwise update it upsert: { set: { street: '1084 Candycane Lane', city: 'Silverlake', zip: '84323', }, update: { zip: '84323', }, }, }, }, }); ``` ### `push` Use `push` to push values to the end of a list of composite types. #### Examples ##### Add a new photo to the `photos` list ```ts const product = prisma.product.update({ where: { id: 10, }, data: { photos: { // Push a photo to the end of the photos list push: [{ height: 100, width: 200, url: '1.jpg' }], }, }, }); ``` ## Composite type filters Available for MongoDB only in Prisma `3.11.0` and later. Composite type filters allow you to filter the contents of [composite types](/orm/prisma-client/special-fields-and-types/composite-types). ### `equals` Use `equals` to filter results by matching a composite type or a list of composite types. Requires all required fields of the composite type to match. #### Remarks When matching optional fields, you need to distinguish between undefined (missing) fields of the document, and fields that have been explicitly set to `null`: - If you omit an optional field, it will match undefined fields, but not fields that have been set to `null` - If you filter for `null` values of an optional field with `equals: { ... exampleField: null ... }`, then it will match only documents where the field has been set to `null`, and not undefined fields The ordering of fields and lists matters when using `equals`: - For fields, `{ "a": "1", "b": "2" }` and `{ "b": "2", "a": "1" }` are not considered equal - For lists, `[ { "a": 1 }, { "a": 2 } ]` and `[ { "a": 2 }, { "a": 1 } ]` are not considered equal #### Examples ##### Find orders that exactly match the given `shippingAddress` ```ts const orders = await prisma.order.findMany({ where: { shippingAddress: { equals: { street: '555 Candy Cane Lane', city: 'Wonderland', zip: '52337', }, }, }, }); ``` ##### Find products with photos that match all of a list of `url`s ```ts const product = prisma.product.findMany({ where: { equals: { photos: [{ url: '1.jpg' }, { url: '2.jpg' }], }, }, }); ``` ### `is` Use `is` to filter results by matching specific fields within composite types. #### Examples ##### Find orders with a `shippingAddress` that matches the given street name ```ts const orders = await prisma.order.findMany({ where: { shippingAddress: { is: { street: '555 Candy Cane Lane', }, }, }, }); ``` ### `isNot` Use `isNot` to filter results for composite type fields that do not match. #### Examples ##### Find orders with a `shippingAddress` that does not match the given zip code ```ts const orders = await prisma.order.findMany({ where: { shippingAddress: { isNot: { zip: '52337', }, }, }, }); ``` ### `isEmpty` Use `isEmpty` to filter results for an empty list of composite types. #### Examples ##### Find products with no photos ```ts const product = prisma.product.findMany({ where: { photos: { isEmpty: true, }, }, }); ``` ### `every` Use `every` to filter for lists of composite types where every item in the list matches the condition #### Examples ##### Find the first product where every photo has a `height` of `200` ```ts const product = await prisma.product.findFirst({ where: { photos: { every: { height: 200, } } }, }) ``` ### `some` Use `some` to filter for lists of composite types where one or more items in the list match the condition. #### Examples ##### Find the first product where one or more photos have a `url` of `2.jpg` ```ts const product = await prisma.product.findFirst({ where: { photos: { some: { url: "2.jpg", } } }, }) ``` ### `none` Use `none` to filter for lists of composite types where no items in the list match the condition. #### Examples ##### Find the first product where no photos have a `url` of `2.jpg` ```ts const product = await prisma.product.findFirst({ where: { photos: { none: { url: "2.jpg", } } }, }) ``` ## Atomic number operations Atomic operations on update is available for number field types (`Float` and `Int`). This feature allows you to update a field based on its **current** value (such as _subtracting_ or _dividing_) without risking a race condition.
Overview: Race conditions A race conditions occurs when two or more operations must be done in sequence in order to complete a task. In the following example, two clients try to increase the same field (`postCount`) by one: | Client | Operation | Value | | :------- | :------------------ | :----- | | Client 1 | **Get** field value | `21` | | Client 2 | **Get** field value | `21` | | Client 2 | **Set** field value | `22` | | Client 1 | **Set** field value | `22` ✘ | The value _should_ be `23`, but the two clients did not read and write to the `postCount` field in sequence. Atomic operations on update combine read and write into a single operation, which prevents a race condition: | Client | Operation | Value | | :------- | :-------------------------- | :----------------- | | Client 1 | **Get and set** field value | `21` → `22` | | Client 2 | **Get and set** field value | `22` → `23` ✔ |
### Operators | Option | Description | | :---------- | :------------------------------------------------------------ | | `increment` | Adds `n` to the current value. | | `decrement` | Subtacts `n` from the current value. | | `multiply` | Multiplies the current value by `n`. | | `divide` | Divides the current value by `n`. | | `set` | Sets the current field value. Identical to `{ myField : n }`. | ### Remarks - You can only perform **one** atomic update per field, per query. - If a field is `null`, it will not be updated by `increment`, `decrement`, `multiply`, or `divide`. ### Examples #### Increment all `view` and `likes` fields of all `Post` records by `1` ```ts const updatePosts = await prisma.post.updateMany({ data: { views: { increment: 1, }, likes: { increment: 1, }, }, }); ``` #### Set all `views` fields of all `Post` records to `0` ```ts const updatePosts = await prisma.post.updateMany({ data: { views: { set: 0, }, }, }); ``` Can also be written as: ```ts const updatePosts = await prisma.post.updateMany({ data: { views: 0, }, }); ``` ## `Json` filters For use cases and advanced examples, see: [Working with `Json` fields](/orm/prisma-client/special-fields-and-types/working-with-json-fields). Supported by [PostgreSQL](/orm/overview/databases/postgresql) and [MySQL](/orm/overview/databases/mysql) with different syntaxes for the `path` option. PostgreSQL does not support filtering on object key values in arrays. The examples in this section assumes that the value of the `pet` field is: ```json { "favorites": { "catBreed": "Turkish van", "dogBreed": "Rottweiler", "sanctuaries": ["RSPCA", "Alley Cat Allies"], "treats": [ { "name": "Dreamies", "manufacturer": "Mars Inc" }, { "name": "Treatos", "manufacturer": "The Dog People" } ] }, "fostered": { "cats": ["Bob", "Alice", "Svetlana the Magnificent", "Queenie"] }, "owned": { "cats": ["Elliott"] } } ``` ### Remarks - The implementation of `Json` filtering [differs between database connectors](/orm/prisma-client/special-fields-and-types/working-with-json-fields) - Filtering is case sensitive in PostgreSQL and does not yet support `mode` ### `path` `path` represents the location of a specific key. The following query returns all users where the nested `favourites` > `dogBreed` key equals `"Rottweiler"`. ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: ['favorites', 'dogBreed'], equals: 'Rottweiler', }, }, }); ``` ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: '$.favorites.dogBreed', equals: 'Rottweiler', }, }, }); ``` The following query returns all users where the nested `owned` > `cats` array contains `"Elliott"`. ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: ['owned', 'cats'], array_contains: ['Elliott'], }, }, }); ``` ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: '$.owned.cats', array_contains: 'Elliott', }, }, }); ``` Filtering by the key values of objects inside an array (below) is only supported by the MySQL connector. The following query returns all users where the nested `favorites` > `treats` array contains an object where the `name` value is `"Dreamies"`: ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: '$.favorites.treats[*].name', array_contains: 'Dreamies', }, }, }); ``` ### `string_contains` The following query returns all users where the nested `favorites` > `catBreed` key value contains `"Van"`: ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: ['favorites', 'catBreed'], string_contains: 'Van', }, }, }); ``` ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: '$.favorites.catBreed', string_contains: 'Van', }, }, }); ``` ### `string_starts_with` The following query returns all users where the nested `favorites` > `catBreed` key value starts with `"Turkish"`: ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: ['favorites', 'catBreed'], string_starts_with: 'Turkish', }, }, }); ``` ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: '$.favorites.catBreed', string_starts_with: 'Turkish', }, }, }); ``` ### `string_ends_with` The following query returns all users where the nested `favorites` \> `catBreed` key value ends with `"Van"`: ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: ['favorites', 'catBreed'], string_ends_with: 'Van', }, }, }); ``` ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: '$.favorites.catBreed', string_ends_with: 'Van', }, }, }); ``` ### `mode` Specify whether the the string filtering should be case sensitive (default) or case insensitive. The following query returns all users where the nested `favorites` > `catBreed` key value contains `"Van"` or `"van"`: ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: ['favorites', 'catBreed'], string_contains: 'Van', mode: "insensitive", }, }, }); ``` ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: '$.favorites.catBreed', string_contains: 'Van', mode: "insensitive", }, }, }); ``` ### `array_contains` The following query returns all users where the `sanctuaries` array contains the value `"RSPCA"`: ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: ['sanctuaries'], array_contains: ['RSPCA'], }, }, }); ``` **Note**: In PostgreSQL, the value of `array_contains` must be an array and not a string, even if the array only contains a single value. ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: '$.sanctuaries', array_contains: 'RSPCA', }, }, }); ``` The following query returns all users where the `sanctuaries` array contains _all_ the values in the given array: ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: ['sanctuaries'], array_contains: ['RSPCA', 'Alley Cat Allies'], }, }, }); ``` ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: '$.sanctuaries', array_contains: ['RSPCA', 'Alley Cat Allies'], }, }, }); ``` ### `array_starts_with` The following query returns all users where the `sanctuaries` array starts with the value `"RSPCA"`: ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: ['sanctuaries'], array_starts_with: 'RSPCA', }, }, }); ``` ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: '$.sanctuaries', array_starts_with: 'RSPCA', }, }, }); ``` ### `array_ends_with` The following query returns all users where the `sanctuaries` array ends with the value `"Alley Cat Allies"`: ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: ['sanctuaries'], array_ends_with: 'Alley Cat Allies', }, }, }); ``` ```ts const getUsers = await prisma.user.findMany({ where: { pets: { path: '$.sanctuaries', array_ends_with: 'Alley Cat Allies', }, }, }); ``` ## Client methods **Note:** Client-level methods are prefixed by `$`. ### Remarks - `$on` and `$use` client methods do not exist on extended client instances which are extended using [`$extends`](#extends) In [extended clients](/orm/prisma-client/client-extensions), Client methods do not necessarily exist. If you are extending your client, make sure to check for existence before using Client methods like `$transaction` or `$connect`. In addition, if you are using `$on` or `$use`, you will need to use these client methods before extending your client as these methods do not exist on extended clients. For `$use` specifically we recommend transitioning [to use query extensions](/orm/prisma-client/client-extensions/query). ### `$disconnect()` The `$disconnect()` method closes the database connections that were established when `$connect` was called and stops the process that was running Prisma ORM's query engine. See [Connection management](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management) for an overview of `$connect()` and `$disconnect()`. #### Remarks - `$disconnect()` returns a `Promise`, so you should call it inside an `async` function with the `await` keyword. ### `$connect()` The `$connect()` method establishes a physical connection to the database via Prisma ORM's query engine. See [Connection management](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management) for an overview of `$connect()` and `$disconnect()`. #### Remarks - `$connect()` returns a `Promise`, so you should call it inside an `async` function with the `await` keyword. ### `$on()` `$on` is not available in [extended clients](/orm/prisma-client/client-extensions). Please either migrate to client extensions or use the `$on` method prior to extending your client. The `$on()` method allows you to subscribe to [logging events](#log) or the [exit hook](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management#exit-hooks). ### `$use()` `$use` is not available in [extended clients](/orm/prisma-client/client-extensions). Please [either migrate to query extensions](/orm/prisma-client/client-extensions/query) or use the `$use` method prior to extending your client. The `$use()` method adds [middleware](/orm/prisma-client/client-extensions/middleware) : ```ts prisma.$use(async (params, next) => { console.log('This is middleware!'); // Modify or interrogate params here return next(params); }); ``` #### `next` `next` represents the "next level" in the middleware stack, which could be the next middleware or the Prisma Query, depending on [where in the stack you are](/orm/prisma-client/client-extensions/middleware#running-order-and-the-middleware-stack). #### `params` `params` is an object with information to use in your middleware. | Parameter | Description | | :----------------- | :--------------------------------------------------------------------------------------------- | | `action` | The query type - for example, `create` or `findMany`. | | `args` | Arguments that were passed into the query - for example, `where`, `data`, or `orderBy` | | `dataPath` | Populated if you use the [fluent API](/orm/prisma-client/queries/relation-queries#fluent-api). | | `model` | The model type - for example, `Post` or `User`. | | `runInTransaction` | Returns `true` if the query ran in the context of a [transaction](#transaction). | :::tip If you need the `model` property as a string, use: `String(params.model)` ::: Example parameter values: ```js { args: { where: { id: 15 } }, dataPath: [ 'select', 'author', 'select', 'posts' ], runInTransaction: false, action: 'findMany', model: 'Post' } ``` #### Examples See [middleware examples](/orm/prisma-client/client-extensions/middleware#samples). ### `$queryRawTyped` See: [Using Raw SQL (`$queryRawTyped`)](/orm/prisma-client/using-raw-sql/typedsql). ### `$queryRaw` See: [Using Raw SQL (`$queryRaw`)](/orm/prisma-client/using-raw-sql/raw-queries#queryraw). ### `$queryRawUnsafe()` See: [Using Raw SQL (`$queryRawUnsafe()`)](/orm/prisma-client/using-raw-sql/raw-queries#queryrawunsafe). ### `$executeRaw` See: [Using Raw SQL (`$executeRaw`)](/orm/prisma-client/using-raw-sql/raw-queries#executeraw). ### `$executeRawUnsafe()` See: [Using Raw SQL (`$executeRawUnsafe()`)](/orm/prisma-client/using-raw-sql/raw-queries#executerawunsafe). ### `$runCommandRaw()` See: [Using Raw SQL (`$runCommandRaw()`)](/orm/prisma-client/using-raw-sql/raw-queries#runcommandraw). ### `$transaction()` See: [Transactions](/orm/prisma-client/queries/transactions). ### `$metrics` Prisma Client metrics give you a detailed insight into how Prisma Client interacts with your database. You can use this insight to help diagnose performance issues with your application. Learn more: [Metrics](/orm/prisma-client/observability-and-logging/metrics). Prisma Client metrics has the following methods: - `$metrics.json()`: [Retrieves Prisma Client metrics in JSON format](/orm/prisma-client/observability-and-logging/metrics#retrieve-metrics-in-json-format). - `$metrics.prometheus()`: [Retrieves Prisma Client metrics in Prometheus format](/orm/prisma-client/observability-and-logging/metrics#retrieve-metrics-in-prometheus-format). ### `$extends` With `$extends`, you can create and use Prisma Client extensions to add functionality to Prisma Client in the following ways: - `model`: add custom methods to your models - `client`: add custom methods to your client - `query`: create custom Prisma Client queries - `result`: add custom fields to your query results Learn more: [Prisma Client extensions](/orm/prisma-client/client-extensions). ## Utility types Utility types are helper functions and types that live on the `Prisma` namespace. They are useful for keeping your application type safe. ### `Prisma.validator` The `validator` helps you create re-usable query parameters based on your schema models while making sure that the objects you create are valid. See also: [Using `Prisma.validator`](/orm/prisma-client/type-safety/prisma-validator) There are two ways you can use the `validator`: #### Using generated Prisma Client types Using types provides a type-level approach to validate data: ```ts Prisma.validator({ args }); ``` #### Using a "selector" When using the selector pattern, you use an existing Prisma Client instance to create a validator. This pattern allows you to select the model, operation, and query option to validate against. You can also use an instance of Prisma Client that has been extended using a [Prisma Client extension](/orm/prisma-client/client-extensions). ```ts Prisma.validator(PrismaClientInstance, '', '', '')({ args }); ``` #### Examples The following example shows how you can extract and validate the input for the `create` operation you can reuse within your app: ```ts import { Prisma } from '@prisma/client'; const validateUserAndPostInput = (name, email, postTitle) => { return Prisma.validator()({ name, email, posts: { create: { title: postTitle, }, }, }); }; ``` Here is an alternative syntax for the same operation: ```ts import { Prisma } from '@prisma/client'; import prisma from './prisma'; const validateUserAndPostInput = (name, email, postTitle) => { return Prisma.validator( prisma, 'user', 'create', 'data' )({ name, email, posts: { create: { title: postTitle, }, }, }); }; ``` ## Compare columns in the same table You can compare columns in the same table directly, for non-unique filters. This feature was moved to general availability in version 5.0.0 and was available via the `fieldReference` Preview feature from Prisma ORM versions 4.3.0 to 4.16.2. In the following situations, you must [use raw queries to compare columns in the same table](/orm/more/help-and-troubleshooting/comparing-columns-through-raw-queries): - If you use a version earlier than 4.3.0 - If you want to use a unique filter, such as [`findUnique`](#findunique) or [`findUniqueOrThrow`](#finduniqueorthrow) - If you want to compare a field with a [unique constraint](/orm/prisma-schema/data-model/models#defining-a-unique-field) - If you want to use one of the following operators to compare a [JSON field](/orm/prisma-client/special-fields-and-types/working-with-json-fields) in MySQL or MariaDB with another field: [`gt`](#gt), [`gte`](#gte), [`lt`](#lt), or [`lte`](#lte). Note that you can use these operators to compare the JSON field with a scalar value. This limitation applies only if you try to compare a JSON field with another field. To compare columns in the same table, use the `.fields` property. In the following example, the query returns all records where the value in the `prisma.product.quantity` field is less than or equal to the value in the `prisma.product.warnQuantity` field. ```ts prisma.product.findMany({ where: { quantity: { lte: prisma.product.fields.warnQuantity } }, }); ``` `fields` is a special property of every model. It contains the list of fields for that model. ### Considerations #### Fields must be of the same type You can only make comparisons on fields of the same type. For example, the following causes an error: ```ts await prisma.order.findMany({ where: { id: { equals: prisma.order.fields.due }, // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // Type error: id is a string, while amountDue is an integer }, }); ``` #### Fields must be in the same model You can only make comparisons with the `fields` property on fields in the same model. The following example does not work: ```ts await prisma.order.findMany({ where: { id: { equals: prisma.user.fields.name }, // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // Type error: name is a field on the User model, not Order }, }); ``` However, you can compare fields in separate models with [standard queries](#model-queries). #### In `groupBy` model queries, put your referenced fields in the `by` argument If you use the [groupBy](#groupby) model query with the `having` option, then you must put your referenced fields in the `by` argument. The following example works: ```ts prisma.user.groupBy({ by: ['id', 'name'], having: { id: { equals: prisma.user.fields.name } }, }); ``` The following example does not work, because `name` is not in the `by` argument: ```ts prisma.user.groupBy({ by: ['id'], having: { id: { equals: prisma.user.fields.name } }, // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // name is not in the 'by' argument }); ``` #### Search for fields in scalar lists If your data source supports scalar lists (for example in PostgreSQL), then you can search for all records where a specific field is in a list of fields. To do so, reference the scalar list with the [`in`](#in) and [`notIn`](#notin) filters. For example: ```ts await prisma.user.findMany({ where: { // find all users where 'name' is in a list of tags name: { in: prisma.user.fields.tags }, }, }); ``` ## Filter on non-unique fields with `UserWhereUniqueInput` From version 5.0.0, the generated type `UserWhereUniqueInput` on [`where`](#where) exposes all fields on the model, not just unique fields. This was available under the [`extendedWhereUnique` Preview flag](/orm/reference/preview-features/client-preview-features#preview-features-promoted-to-general-availability) between versions 4.5.0 to 4.16.2 You must specify at least one unique field in your `where` statement [outside of boolean operators](#boolean-operators-with-userwhereuniqueinput), and you can specify any number of additional unique and non-unique fields. You can use this to add filters to any operation that returns a single record. For example, you can use this feature for the following: - [Optimistic concurrency control on updates](#optimistic-concurrency-control-on-updates) - [Permission checks](#permission-checks) - [Soft deletes](#soft-deletes) From version 4.6.0, you can use this feature to filter on optional [one-to-one nested reads](/orm/prisma-client/queries/relation-queries#nested-reads). ### Optimistic concurrency control on updates You can filter on non-unique fields to perform [optimistic concurrency control](/orm/prisma-client/queries/transactions#optimistic-concurrency-control) on `update` operations. To perform optimistic concurrency control, we recommend that you use a `version` field to check whether the data in a record or related record has changed while your code executes. Before version 4.5.0, you could not evaluate the `version` field in an `update` operation, because the field is non-unique. From version 4.5.0, you can evaluate the `version` field. In the following example, `updateOne` and `updateTwo` first read the same record and then attempt to update it. The database only executes these updates if the value in `version` is the same as the value when it did the initial read. When the database executes the first of these updates (which might be `updateOne` or `updateTwo`, depending on timing), it increments the value in `version`. This means that the database does not execute the second update because the value in `version` has changed. ```prisma model User { id Int @id @default(autoincrement()) email String @unique city String version Int } ``` ```ts function updateOne() { const user = await prisma.user.findUnique({ id: 1 }); await prisma.user.update({ where: { id: user.id, version: user.version }, data: { city: 'Berlin', version: { increment: 1 } }, }); } function updateTwo() { const user = await prisma.user.findUnique({ id: 1 }); await prisma.user.update({ where: { id: user.id, version: user.version }, data: { city: 'New York', version: { increment: 1 } }, }); } function main() { await Promise.allSettled([updateOne(), updateTwo()]); } ``` ### Permission checks You can filter on non-unique fields to check permissions during an update. In the following example, a user wants to update a post title. The `where` statement checks the value in `authorId` to confirm that the user is the author of the post. The application only updates the post title if the user is the post author. ```ts await prisma.post.update({ where: { id: 1, authorId: 1 }, data: { title: 'Updated post title' }, }); ``` ### Soft deletes You can filter on non-unique fields to handle soft deletes. In the following example, we do not want to return a post if it is soft-deleted. The operation only returns the post if the value in `isDeleted` is `false`. ```ts prisma.Post.findUnique({ where: { id: postId, isDeleted: false } }); ``` ### `UserWhereUniqueInput` considerations #### Boolean operators with `UserWhereUniqueInput` With `UserWhereUniqueInput`, you must specify at least one unique field outside of the boolean operators `AND`, `OR`, `NOT`. You can still use these boolean operators in conjunction with any other unique fields or non-unique fields in your filter. In the following example, we test `id`, a unique field, in conjunction with `email`. This is valid. ```ts await prisma.user.update({ where: { id: 1, OR: [{ email: "bob@prisma.io" }, { email: "alice@prisma.io" }] }, // ^^^ Valid: the expression specifies a unique field (`id`) outside of any boolean operators data: { ... } }) // SQL equivalent: // WHERE id = 1 AND (email = "bob@prisma.io" OR email = "alice@prisma.io") ``` The following example is not valid, because there is no unique field outside of any boolean operators: ```ts await prisma.user.update({ where: { OR: [{ email: "bob@prisma.io" }, { email: "alice@prisma.io" }] }, // ^^^ Invalid: the expressions does not contain a unique field outside of boolean operators data: { ... } }) ``` #### One-to-one relations From version 4.5.0, you can filter on non-unique fields in the following operations on [one-to-one relations](/orm/prisma-schema/data-model/relations/one-to-one-relations): - Nested update - Nested upsert - Nested disconnect - Nested delete Prisma Client automatically uses a unique filter to select the appropriate related record. As a result, you do not need to specify a unique filter in your `where` statement with a `WhereUniqueInput` [generated type](#generated-types-for-where). Instead, the `where` statement has a `WhereInput` generated type. You can use this to filter without the restrictions of `WhereUniqueInput`. ##### Nested update example ```ts await prisma.user.update({ where: { id: 1, }, data: { to_one: { // Before Prisma version 4.5.0 update: { field: "updated" } // From Prisma version 4.5.0, you can also do the following: update: { where: { /*WhereInput*/ }, data: { field: "updated" } } } } } }) ``` ##### Nested upsert example ```ts await prisma.user.update({ where: { id: 1, }, data: { to_one: { upsert: { where: { /* WhereInput */ } // new argument from Prisma 4.5.0 create: { /* CreateInput */ }, update: { /* CreateInput */ }, } } } }) ``` ##### Nested disconnect example ```ts await prisma.user.update({ where: { id: 1, }, data: { to_one: { // Before Prisma version 4.5.0 disconnect: true // From Prisma version 4.5.0, you can also do the following: disconnect: { /* WhereInput */ } } } }) ``` ##### Nested delete example ```ts await prisma.user.update({ where: { id: 1, }, data: { to_one: { // Before Prisma version 4.5.0 delete: true // From Prisma version 4.5.0, you can also do the following: delete: { /* WhereInput */ } } } }) ``` ## `PrismaPromise` behavior All Prisma Client queries return an instance of `PrismaPromise`. This is a ["thenable"](https://masteringjs.io/tutorials/fundamentals/thenable), meaning a `PrismaPromise` only executes when you call `await` or `.then()` or `.catch()`. This behavior is different from a regular JavaScript [`Promise`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise), which starts executing immediately. For example: ```ts const findPostOperation = prisma.post.findMany({}); // Query not yet executed findPostOperation.then(); // Prisma Client now executes the query // or await findPostOperation; // Prisma Client now executes the query ``` When using the [`$transaction` API](/orm/prisma-client/queries/transactions#the-transaction-api), this behavior makes it possible for Prisma Client to pass all the queries on to the query engine as a single transaction. --- # Prisma schema reference URL: https://www.prisma.io/docs/orm/reference/prisma-schema-reference ## `datasource` Defines a [data source](/orm/prisma-schema/overview/data-sources) in the Prisma schema. ### Fields A `datasource` block accepts the following fields: | Name | Required | Type | Description | | ------------------- | -------- | ------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `provider` | **Yes** | String (`postgresql`, `mysql`, `sqlite`, `sqlserver`, `mongodb`, `cockroachdb`) | Describes which data source connectors to use. | | `url` | **Yes** | String (URL) | Connection URL including authentication info. Most connectors use [the syntax provided by the database](/orm/reference/connection-urls#format). | | `shadowDatabaseUrl` | No | String (URL) | Connection URL to the shadow database used by Prisma Migrate. Allows you to use a cloud-hosted database as the shadow database. | | `directUrl` | No | String (URL) | Connection URL for direct connection to the database.

If you use a connection pooler URL in the `url` argument (for example, if you use [Prisma Accelerate](/accelerate) or pgBouncer), Prisma CLI commands that require a direct connection to the database use the URL in the `directUrl` argument.

The `directUrl` property is supported by Prisma Studio from version 5.1.0 upwards.

The `directUrl` property is not needed when using [Prisma Postgres](/postgres) database. | | `relationMode` | No | String (`foreignKeys`, `prisma`) | Sets whether [referential integrity](/orm/prisma-schema/data-model/relations/relation-mode) is enforced by foreign keys in the database or emulated in the Prisma Client.

In preview in versions 3.1.1 and later. The field is named `relationMode` in versions 4.5.0 and later, and was previously named `referentialIntegrity`. | | `extensions` | No | List of strings (PostgreSQL extension names) | Allows you to [represent PostgreSQL extensions in your schema](/orm/prisma-schema/postgresql-extensions#how-to-represent-postgresql-extensions-in-your-prisma-schema). Available in preview for PostgreSQL only in Prisma ORM versions 4.5.0 and later. | The following providers are available: - [`sqlite`](/orm/overview/databases/sqlite) - [`postgresql`](/orm/overview/databases/postgresql) - [`mysql`](/orm/overview/databases/mysql) - [`sqlserver`](/orm/overview/databases/sql-server) - [`mongodb`](/orm/overview/databases/mongodb) - [`cockroachdb`](/orm/overview/databases/cockroachdb) ### Remarks - You can only have **one** `datasource` block in a schema. - `datasource db` is convention - however, you can give your data source any name - for example, `datasource mysql` or `datasource data`. ### Examples #### Specify a PostgreSQL data source In this example, the target database is available with the following credentials: - User: `johndoe` - Password: `mypassword` - Host: `localhost` - Port: `5432` - Database name: `mydb` - Schema name: `public` ```prisma datasource db { provider = "postgresql" url = "postgresql://johndoe:mypassword@localhost:5432/mydb?schema=public" } ``` Learn more about PostgreSQL connection strings [here](/orm/overview/databases/postgresql). #### Specify a PostgreSQL data source via an environment variable In this example, the target database is available with the following credentials: - User: `johndoe` - Password: `mypassword` - Host: `localhost` - Port: `5432` - Database name: `mydb` - Schema name: `public` ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` When running a Prisma CLI command that needs the database connection URL (e.g. `prisma generate`), you need to make sure that the `DATABASE_URL` environment variable is set. One way to do so is by creating a [`.env`](https://github.com/motdotla/dotenv) file with the following contents. Note that the file must be in the same directory as your `schema.prisma` file to automatically picked up the Prisma CLI. ``` DATABASE_URL=postgresql://johndoe:mypassword@localhost:5432/mydb?schema=public ``` #### Specify a MySQL data source In this example, the target database is available with the following credentials: - User: `johndoe` - Password: `mypassword` - Host: `localhost` - Port: `3306` - Database name: `mydb` ```prisma datasource db { provider = "mysql" url = "mysql://johndoe:mypassword@localhost:3306/mydb" } ``` Learn more about MySQL connection strings [here](/orm/overview/databases/mysql). #### Specify a MongoDB data source - User: `root` - Password: `password` - Host: `cluster1.test1.mongodb.net` - Port: N/A - Database name: `testing` ```prisma datasource db { provider = "mongodb" url = "mongodb+srv://root:password@cluster1.test1.mongodb.net/testing?retryWrites=true&w=majority" } ``` Learn more about MongoDB connection strings [here](/orm/overview/databases/mongodb). #### Specify a SQLite data source In this example, the target database is located in a file called `dev.db`: ```prisma datasource db { provider = "sqlite" url = "file:./dev.db" } ``` Learn more about SQLite connection strings [here](/orm/overview/databases/sqlite). #### Specify a CockroachDB data source In this example, the target database is available with the following credentials: - User: `johndoe` - Password: `mypassword` - Host: `localhost` - Port: `26257` - Database name: `mydb` - Schema name: `public` ```prisma datasource db { provider = "cockroachdb" url = "postgresql://johndoe:mypassword@localhost:26257/mydb?schema=public" } ``` The format for connection strings is the same as for PostgreSQL. Learn more about PostgreSQL connection strings [here](/orm/overview/databases/postgresql). ## `generator` Defines a [generator](/orm/prisma-schema/overview/generators) in the Prisma schema. ### Fields A `generator` block accepts the following fields: | Name | Required | Type | Description | | :-----------------| :----------------------- | :----------------------- | :----------------------- | | `provider` | **Yes** | String (file path) or Enum (`prisma-client-js` or `prisma-client`) | Describes which [generator](/orm/prisma-schema/overview/generators) to use. This can point to a file that implements a generator or specify a built-in generator directly. | | `output` | No* | String (file path) | Determines the location for the generated client, [learn more](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path). **Default**: `node_modules/.prisma/client` | | `previewFeatures` | No | List of Enums | Use intellisense to see list of currently available Preview features (`Ctrl+Space` in Visual Studio Code) **Default**: none | | | `engineType` | No | Enum (`library` or `binary`) | Defines the [query engine](/orm/more/under-the-hood/engines) type to download and use. **Default**: `library` | | `binaryTargets` | No | List of Enums (see below) | Specify the OS on which the Prisma Client will run to ensure compatibility of the [query engine](/orm/more/under-the-hood/engines). **Default**: `native` | :::note[important] We recommend defining a custom output path, adding the path to `.gitignore`, and then making sure to run `prisma generate` via a custom build script or postinstall hook. ::: #### `binaryTargets` options The following tables list all supported operating systems with the name of platform to specify in [`binaryTargets`](/orm/prisma-schema/overview/generators#binary-targets). Unless specified otherwise, the default supported CPU architecture is x86_64. ##### macOS | Build OS | Prisma engine build name | | :----------------- | :----------------------- | | macOS Intel x86_64 | `darwin` | | macOS ARM64 | `darwin-arm64` | ##### Windows | Build OS | Prisma engine build name | | :------- | :----------------------- | | Windows | `windows` | ##### Linux (Alpine on x86_64 architectures) | Build OS | Prisma engine build name | OpenSSL | | :---------------------- | :--------------------------- | :-----: | | Alpine (3.17 and newer) | `linux-musl-openssl-3.0.x`\* | 3.0.x | | Alpine (3.16 and older) | `linux-musl` | 1.1.x | \* Available in Prisma ORM versions 4.8.0 and later. ##### Linux (Alpine on ARM64 architectures) | Build OS | Prisma engine build name | OpenSSL | | :---------------------- | :--------------------------------- | :-----: | | Alpine (3.17 and newer) | `linux-musl-arm64-openssl-3.0.x`\* | 3.0.x | | Alpine (3.16 and older) | `linux-musl-arm64-openssl-1.1.x`\* | 1.1.x | \* Available in Prisma ORM versions 4.10.0 and later. ##### Linux (Debian), x86_64 | Build OS | Prisma engine build name | OpenSSL | | :------------------- | :----------------------- | :-----: | | Debian 8 (Jessie) | `debian-openssl-1.0.x` | 1.0.x | | Debian 9 (Stretch) | `debian-openssl-1.1.x` | 1.1.x | | Debian 10 (Buster) | `debian-openssl-1.1.x` | 1.1.x | | Debian 11 (Bullseye) | `debian-openssl-1.1.x` | 1.1.x | | Debian 12 (Bookworm) | `debian-openssl-3.0.x` | 3.0.x | ##### Linux (Ubuntu), x86_64 | Build OS | Prisma engine build name | OpenSSL | | :--------------------- | :----------------------- | :-----: | | Ubuntu 14.04 (trusty) | `debian-openssl-1.0.x` | 1.0.x | | Ubuntu 16.04 (xenial) | `debian-openssl-1.0.x` | 1.0.x | | Ubuntu 18.04 (bionic) | `debian-openssl-1.1.x` | 1.1.x | | Ubuntu 19.04 (disco) | `debian-openssl-1.1.x` | 1.1.x | | Ubuntu 20.04 (focal) | `debian-openssl-1.1.x` | 1.1.x | | Ubuntu 21.04 (hirsute) | `debian-openssl-1.1.x` | 1.1.x | | Ubuntu 22.04 (jammy) | `debian-openssl-3.0.x` | 3.0.x | | Ubuntu 23.04 (lunar) | `debian-openssl-3.0.x` | 3.0.x | ##### Linux (CentOS), x86_64 | Build OS | Prisma engine build name | OpenSSL | | :------- | :----------------------- | :-----: | | CentOS 7 | `rhel-openssl-1.0.x` | 1.0.x | | CentOS 8 | `rhel-openssl-1.1.x` | 1.1.x | ##### Linux (Fedora), x86_64 | Build OS | Prisma engine build name | OpenSSL | | :-------- | :----------------------- | :-----: | | Fedora 28 | `rhel-openssl-1.1.x` | 1.1.x | | Fedora 29 | `rhel-openssl-1.1.x` | 1.1.x | | Fedora 30 | `rhel-openssl-1.1.x` | 1.1.x | | Fedora 36 | `rhel-openssl-3.0.x` | 3.0.x | | Fedora 37 | `rhel-openssl-3.0.x` | 3.0.x | | Fedora 38 | `rhel-openssl-3.0.x` | 3.0.x | ##### Linux (Linux Mint), x86_64 | Build OS | Prisma engine build name | OpenSSL | | :------------ | :----------------------- | :-----: | | Linux Mint 18 | `debian-openssl-1.0.x` | 1.0.x | | Linux Mint 19 | `debian-openssl-1.1.x` | 1.1.x | | Linux Mint 20 | `debian-openssl-1.1.x` | 1.1.x | | Linux Mint 21 | `debian-openssl-3.0.x` | 3.0.x | ##### Linux (Arch Linux), x86_64 | Build OS | Prisma engine build name | OpenSSL | | :-------------------- | :----------------------- | :-----: | | Arch Linux 2019.09.01 | `debian-openssl-1.1.x` | 1.1.x | | Arch Linux 2023.04.23 | `debian-openssl-3.0.x` | 3.0.x | ##### Linux ARM64 (all major distros but Alpine) | Build OS | Prisma engine build name | OpenSSL | | :----------------------------- | :-------------------------- | :-----: | | Linux ARM64 glibc-based distro | `linux-arm64-openssl-1.0.x` | 1.0.x | | Linux ARM64 glibc-based distro | `linux-arm64-openssl-1.1.x` | 1.1.x | | Linux ARM64 glibc-based distro | `linux-arm64-openssl-3.0.x` | 3.0.x | ### Examples #### Specify the `prisma-client-js` generator with the default `output`, `previewFeatures`, `engineType` and `binaryTargets` ```prisma generator client { provider = "prisma-client-js" } ``` Note that the above `generator` definition is **equivalent** to the following because it uses the default values for `output`, `engineType` and `binaryTargets` (and implicitly `previewFeatures`): ```prisma generator client { provider = "prisma-client-js" output = "node_modules/.prisma/client" engineType = "library" binaryTargets = ["native"] } ``` #### Specify a custom `output` location for Prisma Client This example shows how to define a custom `output` location of the generated asset to override the default one. ```prisma generator client { provider = "prisma-client-js" output = "../src/generated/client" } ``` #### Specify custom `binaryTargets` to ensure compatibility with the OS This example shows how to configure Prisma Client to run on `Ubuntu 19.04 (disco)` based on the table [above](#linux-ubuntu-x86_64). ```prisma generator client { provider = "prisma-client-js" binaryTargets = ["debian-openssl-1.1.x"] } ``` #### Specify a `provider` pointing to some custom generator implementation This example shows how to use a custom generator that's located in a directory called `my-generator`. ```prisma generator client { provider = "./my-generator" } ``` ## `model` Defines a Prisma [model](/orm/prisma-schema/data-model/models#defining-models) . ### Remarks - Every record of a model must be _uniquely_ identifiable. You must define _at least_ one of the following attributes per model: - [`@unique`](#unique) - [`@@unique`](#unique-1) - [`@id`](#id) - [`@@id`](#id-1) #### Naming conventions - Model names must adhere to the following regular expression: `[A-Za-z][A-Za-z0-9_]*` - Model names must start with a letter and are typically spelled in [PascalCase](https://wiki.c2.com/?PascalCase) - Model names should use the singular form (for example, `User` instead of `user`, `users` or `Users`) - Prisma ORM has a number of **reserved words** that are being used by Prisma ORM internally and therefore cannot be used as a model name. You can find the reserved words [here](https://github.com/prisma/prisma/blob/6.5.0/packages/client/src/generation/generateClient.ts#L556-L605) and [here](https://github.com/prisma/prisma-engines/blob/main/psl/parser-database/src/names/reserved_model_names.rs#L44). > **Note**: You can use the [`@@map` attribute](#map-1) to map a model (for example, `User`) to a table with a different name that does not match model naming conventions (for example, `users`). #### Order of fields - In version 2.3.0 and later, introspection lists model fields in the same order as the corresponding columns in the database. Relation fields are listed after scalar fields. ### Examples #### A model named `User` with two scalar fields ```prisma model User { email String @unique // `email` can not be optional because it's the only unique field on the model name String? } ``` ```prisma model User { id String @default(auto()) @map("_id") @db.ObjectId email String @unique name String? } ``` ## `model` fields [Fields](/orm/prisma-schema/data-model/models#defining-fields) are properties of models. ### Remarks #### Naming conventions - Must start with a letter - Typically spelled in camelCase - Must adhere to the following regular expression: `[A-Za-z][A-Za-z0-9_]*` > **Note**: You can use the [`@map` attribute](#map) to [map a field name to a column](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) with a different name that does not match field naming conventions: e.g. `myField @map("my_field")`. ## `model` field scalar types The _data source connector_ determines what _native database type_ each of Prisma ORM scalar type maps to. Similarly, the _generator_ determines what _type in the target programming language_ each of these types map to. Prisma models also have [model field types](/orm/prisma-schema/data-model/relations) that define relations between models. ### `String` Variable length text. #### Default type mappings | Connector | Default mapping | | ----------- | ---------------- | | PostgreSQL | `text` | | SQL Server | `nvarchar(1000)` | | MySQL | `varchar(191)` | | MongoDB | `String` | | SQLite | `TEXT` | | CockroachDB | `STRING` | #### PostgreSQL | Native database type | Native database type attribute | Notes | | :------------------- | :----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `text` | `@db.Text` | | | `char(x)` | `@db.Char(x)` | | `varchar(x)` | `@db.VarChar(x)` | | `bit(x)` | `@db.Bit(x)` | | `varbit` | `@db.VarBit` | | `uuid` | `@db.Uuid` | | `xml` | `@db.Xml` | | `inet` | `@db.Inet` | | `citext` | `@db.Citext` | Only available if [Citext extension is enabled](/orm/prisma-schema/data-model/unsupported-database-features#enable-postgresql-extensions-for-native-database-functions). | #### MySQL | Native database type | Native database type attribute | | :------------------- | :----------------------------- | | `VARCHAR(x)` | `@db.VarChar(x)` | | `TEXT` | `@db.Text` | | `CHAR(x)` | `@db.Char(x)` | | `TINYTEXT` | `@db.TinyText` | | `MEDIUMTEXT` | `@db.MediumText` | | `LONGTEXT` | `@db.LongText` | You can use Prisma Migrate to map `@db.Bit(1)` to `String`: ```prisma model Model { /* ... */ myField String @db.Bit(1) } ``` #### MongoDB `String` | Native database type attribute | Notes | | :----------------------------- | :-------------------------------------------------------------------------------- | | `@db.String` | | | `@db.ObjectId` | Required if the underlying BSON type is `OBJECT_ID` (ID fields, relation scalars) | #### Microsoft SQL Server | Native database type | Native database type attribute | | :------------------- | :----------------------------- | | `char(x)` | `@db.Char(x)` | | `nchar(x)` | `@db.NChar(x)` | | `varchar(x)` | `@db.VarChar(x)` | | `nvarchar(x)` | `@db.NVarChar(x)` | | `text` | `@db.Text` | | `ntext` | `@db.NText` | | `xml` | `@db.Xml` | | `uniqueidentifier` | `@db.UniqueIdentifier` | #### SQLite `TEXT` #### CockroachDB | Native database type | Native database type attribute | Notes | | :--------------------------------------- | :----------------------------- | ----- | | `STRING(x)` \| `TEXT(x)` \| `VARCHAR(x)` | `@db.String(x)` | | | `CHAR(x)` | `@db.Char(x)` | | | `"char"` | `@db.CatalogSingleChar` | | | `BIT(x)` | `@db.Bit(x)` | | | `VARBIT` | `@db.VarBit` | | | `UUID` | `@db.Uuid` | | | `INET` | `@db.Inet` | | Note that the `xml` and `citext` types supported in PostgreSQL are not currently supported in CockroachDB. #### Clients | Prisma Client JS | | ---------------- | | `string` | ### `Boolean` True or false value. #### Default type mappings | Connector | Default mapping | | ----------- | --------------- | | PostgreSQL | `boolean` | | SQL Server | `bit` | | MySQL | `TINYINT(1)` | | MongoDB | `Bool` | | SQLite | `INTEGER` | | CockroachDB | `BOOL` | #### PostgreSQL | Native database types | Native database type attribute | Notes | | :-------------------- | :----------------------------- | ----- | | `boolean` | `@db.Boolean` | | #### MySQL | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------- | | `TINYINT(1)` | `@db.TinyInt(1)` | `TINYINT` maps to `Int` if the max length is greater than 1 (for example, `TINYINT(2)`) _or_ the default value is anything other than `1`, `0`, or `NULL` | | `BIT(1)` | `@db.Bit` | #### MongoDB `Bool` #### Microsoft SQL Server | Native database types | Native database type attribute | Notes | | :-------------------- | :----------------------------- | ----- | | `bit` | `@db.Bit` | | #### SQLite `INTEGER` #### CockroachDB | Native database types | Native database type attribute | Notes | | :-------------------- | :----------------------------- | ----- | | `BOOL` | `@db.Bool` | | #### Clients | Prisma Client JS | | ---------------- | | `boolean` | ### `Int` #### Default type mappings | Connector | Default mapping | | ----------- | --------------- | | PostgreSQL | `integer` | | SQL Server | `int` | | MySQL | `INT` | | MongoDB | `Int` | | SQLite | `INTEGER` | | CockroachDB | `INT` | #### PostgreSQL | Native database types | Native database type attribute | Notes | | -------------------------- | ---------------------------------------- | ----- | | `integer` \| `int`, `int4` | `@db.Integer` | | | `smallint` \| `int2` | `@db.SmallInt` | | | `smallserial` \| `serial2` | `@db.SmallInt @default(autoincrement())` | | | `serial` \| `serial4` | `@db.Int @default(autoincrement())` | | | `oid` | `@db.Oid` | | #### MySQL | Native database types | Native database type attribute | Notes | | :-------------------- | :----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `INT` | `@db.Int` | | | `INT UNSIGNED` | `@db.UnsignedInt` | | | `SMALLINT` | `@db.SmallInt` | | `SMALLINT UNSIGNED` | `@db.UnsignedSmallInt` | | `MEDIUMINT` | `@db.MediumInt` | | `MEDIUMINT UNSIGNED` | `@db.UnsignedMediumInt` | | `TINYINT` | `@db.TinyInt` | `TINYINT` maps to `Int` if the max length is greater than 1 (for example, `TINYINT(2)`) _or_ the default value is anything other than `1`, `0`, or `NULL`. `TINYINT(1)` maps to `Boolean`. | | `TINYINT UNSIGNED` | `@db.UnsignedTinyInt` | `TINYINT(1) UNSIGNED` maps to `Int`, not `Boolean` | | `YEAR` | `@db.Year` | #### MongoDB `Int` | Native database type attribute | Notes | | :----------------------------- | :---- | | `@db.Int` | | | `@db.Long` | | #### Microsoft SQL Server | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | ----- | | `int` | `@db.Int` | | | `smallint` | `@db.SmallInt` | | | `tinyint` | `@db.TinyInt` | | | `bit` | `@db.Bit` | #### SQLite `INTEGER` #### CockroachDB | Native database types | Native database type attribute | Notes | | ---------------------------- | ------------------------------------ | ----------------------------------------------------------------------------------------------------------------- | | `INTEGER` \| `INT` \| `INT8` | `@db.Int8` | Note that this differs from PostgreSQL, where `integer` and `int` are aliases for `int4` and map to `@db.Integer` | | `INT4` | `@db.Int4` | | | `INT2` \| `SMALLINT` | `@db.Int2` | | | `SMALLSERIAL` \| `SERIAL2` | `@db.Int2 @default(autoincrement())` | | | `SERIAL` \| `SERIAL4` | `@db.Int4 @default(autoincrement())` | | | `SERIAL8` \| `BIGSERIAL` | `@db.Int8 @default(autoincrement())` | | #### Clients | Prisma Client JS | | ---------------- | | `number` | ### `BigInt` `BigInt` is available in version [2.17.0](https://github.com/prisma/prisma/releases/tag/2.17.0) and later. #### Default type mappings | Connector | Default mapping | | ----------- | --------------- | | PostgreSQL | `bigint` | | SQL Server | `int` | | MySQL | `BIGINT` | | MongoDB | `Long` | | SQLite | `INTEGER` | | CockroachDB | `INTEGER` | #### PostgreSQL | Native database types | Native database type attribute | Notes | | ------------------------ | -------------------------------------- | ----- | | `bigint` \| `int8` | `@db.BigInt` | | | `bigserial` \| `serial8` | `@db.BigInt @default(autoincrement())` | | #### MySQL | Native database types | Native database type attribute | Notes | | --------------------- | ---------------------------------------------- | ----- | | `BIGINT` | `@db.BigInt` | | | `SERIAL` | `@db.UnsignedBigInt @default(autoincrement())` | | #### MongoDB `Long` #### Microsoft SQL Server | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | ----- | | `bigint` | `@db.BigInt` | | #### SQLite `INTEGER` #### CockroachDB | Native database types | Native database type attribute | Notes | | --------------------------- | ------------------------------------ | -------------------------------------------------------------------------- | | `BIGINT` \| `INT` \| `INT8` | `@db.Int8` | Note that this differs from PostgreSQL, where `int` is an alias for `int4` | | `bigserial` \| `serial8` | `@db.Int8 @default(autoincrement())` | | #### Clients | Client | Type | Description | | :--------------- | :-------------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------- | | Prisma Client JS | [`BigInt`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) | See [examples of working with `BigInt`](/orm/prisma-client/special-fields-and-types#working-with-bigint) | ### `Float` Floating point number. > `Float` maps to `Double` in [2.17.0](https://github.com/prisma/prisma/releases/tag/2.17.0) and later - see [release notes](https://github.com/prisma/prisma/releases/tag/2.17.0) and [Video: Changes to the default mapping of Float in Prisma ORM 2.17.0](https://www.youtube.com/watch?v=OsuGP_xNHco&%3Bab_channel=Prisma) for more information about this change. #### Default type mappings | Connector | Default mapping | | ----------- | ------------------ | | PostgreSQL | `double precision` | | SQL Server | `float(53)` | | MySQL | `DOUBLE` | | MongoDB | `Double` | | SQLite | `REAL` | | CockroachDB | `DOUBLE PRECISION` | #### PostgreSQL | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | ----- | | `double precision` | `@db.DoublePrecision` | | | `real` | `@db.Real` | | #### MySQL | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | ----- | | `FLOAT` | `@db.Float` | | `DOUBLE` | `@db.Double` | #### MongoDB `Double` #### Microsoft SQL Server | Native database types | Native database type attribute | | --------------------- | ------------------------------ | | `float` | `@db.Float` | | `money` | `@db.Money` | | `smallmoney` | `@db.SmallMoney` | | `real` | `@db.Real` | #### SQLite connector `REAL` #### CockroachDB | Native database types | Native database type attribute | Notes | | ------------------------------ | ------------------------------ | ----- | | `DOUBLE PRECISION` \| `FLOAT8` | `@db.Float8` | | | `REAL` \| `FLOAT4` \| `FLOAT` | `@db.Float4` | | #### Clients | Prisma Client JS | | ---------------- | | `number` | ### `Decimal` #### Default type mappings | Connector | Default mapping | | ----------- | -------------------------------------------------------------- | | PostgreSQL | `decimal(65,30)` | | SQL Server | `decimal(32,16)` | | MySQL | `DECIMAL(65,30)` | | MongoDB | [Not supported](https://github.com/prisma/prisma/issues/12637) | | SQLite | `DECIMAL` | | CockroachDB | `DECIMAL` | #### PostgreSQL | Native database types | Native database type attribute | Notes | | ---------------------- | ------------------------------ | ----- | | `decimal` \| `numeric` | `@db.Decimal(p, s)`† | | | `money` | `@db.Money` | | - † `p` (precision), the maximum total number of decimal digits to be stored. `s` (scale), the number of decimal digits that are stored to the right of the decimal point. #### MySQL | Native database types | Native database type attribute | Notes | | ---------------------- | ------------------------------ | ----- | | `DECIMAL` \| `NUMERIC` | `@db.Decimal(p, s)`† | | - † `p` (precision), the maximum total number of decimal digits to be stored. `s` (scale), the number of decimal digits that are stored to the right of the decimal point. #### MongoDB [Not supported](https://github.com/prisma/prisma/issues/12637). #### Microsoft SQL Server | Native database types | Native database type attribute | Notes | | ---------------------- | ------------------------------ | ----- | | `decimal` \| `numeric` | `@db.Decimal(p, s)`† | | - † `p` (precision), the maximum total number of decimal digits to be stored. `s` (scale), the number of decimal digits that are stored to the right of the decimal point. #### SQLite `DECIMAL` (changed from `REAL` in 2.17.0) #### CockroachDB | Native database types | Native database type attribute | Notes | | ------------------------------- | ------------------------------ | ------------------------------------------------------------- | | `DECIMAL` \| `DEC` \| `NUMERIC` | `@db.Decimal(p, s)`† | | | `money` | Not yet | PostgreSQL's `money` type is not yet supported by CockroachDB | - † `p` (precision), the maximum total number of decimal digits to be stored. `s` (scale), the number of decimal digits that are stored to the right of the decimal point. #### Clients | Client | Type | Description | | :--------------- | :------------------------------------------------- | :--------------------------------------------------------------------------------------------------------- | | Prisma Client JS | [`Decimal`](https://mikemcl.github.io/decimal.js/) | See [examples of working with `Decimal`](/orm/prisma-client/special-fields-and-types#working-with-decimal) | ### `DateTime` #### Remarks - Prisma Client returns all `DateTime` as native [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) objects. - Currently, Prisma ORM [does not support](https://github.com/prisma/prisma/issues/5006) [zero dates](https://dev.mysql.com/doc/refman/8.3/en/date-and-time-types.html#:~:text=The%20following%20table%20shows%20the%20format%20of%20the%20%E2%80%9Czero%E2%80%9D%20value%20for%20each%20type) (`0000-00-00 00:00:00`, `0000-00-00`, `00:00:00`) in MySQL. - There currently is a [bug](https://github.com/prisma/prisma/issues/9516) that doesn't allow you to pass in `DateTime` values as strings and produces a runtime error when you do. `DateTime` values need to be passed as [`Date`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) objects (i.e. `new Date('2024-12-04')` instead of `'2024-12-04'`). You can find more info and examples in this section: [Working with `DateTime`](/orm/prisma-client/special-fields-and-types#working-with-datetime). #### Default type mappings | Connector | Default mapping | | ----------- | --------------- | | PostgreSQL | `timestamp(3)` | | SQL Server | `datetime2` | | MySQL | `DATETIME(3)` | | MongoDB | `Timestamp` | | SQLite | `NUMERIC` | | CockroachDB | `TIMESTAMP` | #### PostgreSQL | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | ----- | | `timestamp(x)` | `@db.Timestamp(x)` | | | `timestamptz(x)` | `@db.Timestamptz(x)` | | | `date` | `@db.Date` | | | `time(x)` | `@db.Time(x)` | | | `timetz(x)` | `@db.Timetz(x)` | | #### MySQL | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | ----- | | `DATETIME(x)` | `@db.DateTime(x)` | | | `DATE(x)` | `@db.Date(x)` | | `TIME(x)` | `@db.Time(x)` | | `TIMESTAMP(x)` | `@db.Timestamp(x)` | You can also use MySQL's `YEAR` type with `Int`: ```prisma yearField Int @db.Year ``` #### MongoDB `Timestamp` #### Microsoft SQL Server | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | ----- | | `date` | `@db.Date` | | `time` | `@db.Time` | | `datetime` | `@db.DateTime` | | `datetime2` | `@db.DateTime2` | | | `smalldatetime` | `@db.SmallDateTime` | | `datetimeoffset` | `@db.DateTimeOffset` | #### SQLite `NUMERIC` or `STRING`. If the underlying data type is `STRING`, you must use one of the following formats: - [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) (`1996-12-19T16:39:57-08:00`) - [RFC 2822](https://datatracker.ietf.org/doc/html/rfc2822#section-3.3) (`Tue, 1 Jul 2003 10:52:37 +0200`) #### CockroachDB | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | ----- | | `TIMESTAMP(x)` | `@db.Timestamp(x)` | | | `TIMESTAMPTZ(x)` | `@db.Timestamptz(x)` | | | `DATE` | `@db.Date` | | | `TIME(x)` | `@db.Time(x)` | | | `TIMETZ(x)` | `@db.Timetz(x)` | | #### Clients | Prisma Client JS | | ---------------- | | `Date` | ### `Json` A JSON object. #### Default type mappings | Connector | Default mapping | | ----------- | ------------------------------------------------------------------------------------------------------------ | | PostgreSQL | `jsonb` | | SQL Server | [Not supported](https://github.com/prisma/prisma/issues/7417) | | MySQL | `JSON` | | MongoDB | [A valid `BSON` object (Relaxed mode)](https://www.mongodb.com/docs/manual/reference/mongodb-extended-json/) | | SQLite | `JSONB` | | CockroachDB | `JSONB` | #### PostgreSQL | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | ----- | | `json` | `@db.Json` | | `jsonb` | `@db.JsonB` | | #### MySQL | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | ----- | | `JSON` | `@db.Json` | #### MongoDB [A valid `BSON` object (Relaxed mode)](https://www.mongodb.com/docs/manual/reference/mongodb-extended-json/) #### Microsoft SQL Server Microsoft SQL Server does not have a specific data type for JSON. However, there are a number of [built-in functions for reading and modifying JSON](https://learn.microsoft.com/en-us/sql/relational-databases/json/json-data-sql-server?view=sql-server-ver15#extract-values-from-json-text-and-use-them-in-queries). #### SQLite Not supported #### CockroachDB | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | ----- | | `JSON` \| `JSONB` | `@db.JsonB` | | #### Clients | Prisma Client JS | | ---------------- | | `object` | ### `Bytes` `Bytes` is available in version [2.17.0](https://github.com/prisma/prisma/releases/tag/2.17.0) and later. #### Default type mappings | Connector | Default mapping | | ----------- | --------------- | | PostgreSQL | `bytea` | | SQL Server | `varbinary` | | MySQL | `LONGBLOB` | | MongoDB | `BinData` | | SQLite | `BLOB` | | CockroachDB | `BYTES` | #### PostgreSQL | Native database types | Native database type attribute | | --------------------- | ------------------------------ | | `bytea` | `@db.ByteA` | #### MySQL | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | ----- | | `LONGBLOB` | `@db.LongBlob` | | | `BINARY` | `@db.Binary` | | `VARBINARY` | `@db.VarBinary` | | `TINYBLOB` | `@db.TinyBlob` | | `BLOB` | `@db.Blob` | | `MEDIUMBLOB` | `@db.MediumBlob` | | `BIT` | `@db.Bit` | #### MongoDB `BinData` | Native database type attribute | Notes | | :----------------------------- | :-------------------------------------------------------------------------------- | | `@db.ObjectId` | Required if the underlying BSON type is `OBJECT_ID` (ID fields, relation scalars) | | `@db.BinData` | | #### Microsoft SQL Server | Native database types | Native database type attribute | Notes | | --------------------- | ------------------------------ | ----- | | `binary` | `@db.Binary` | | `varbinary` | `@db.VarBinary` | | | `image` | `@db.Image` | #### SQLite `BLOB` #### CockroachDB | Native database types | Native database type attribute | | ---------------------------- | ------------------------------ | | `BYTES` \| `BYTEA` \| `BLOB` | `@db.Bytes` | #### Clients | Client | Type | Description | | :------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------------------- | | Prisma Client JS | [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) | See [examples of working with `Bytes`](/orm/prisma-client/special-fields-and-types#working-with-bytes) | | Prisma Client JS ([before v6](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6)) | [`Buffer`](https://nodejs.org/api/buffer.html) | See [examples of working with `Bytes`](/orm/prisma-client/special-fields-and-types#working-with-bytes) | ### `Unsupported` **Not supported by MongoDB**
The [MongoDB connector](/orm/overview/databases/mongodb) does not support the `Unsupported` type.
The `Unsupported` type was introduced in [2.17.0](https://github.com/prisma/prisma/releases/tag/2.17.0) and allows you to represent data types in the Prisma schema that are not supported by Prisma Client. Fields of type `Unsupported` can be created during Introspection with `prisma db pull` or written by hand, and created in the database with Prisma Migrate or `db push`. #### Remarks - Fields with `Unsupported` types are not available in the generated client. - If a model contains a **required** `Unsupported` type, `prisma.model.create(..)`, `prisma.model.update(...)` and `prisma.model.upsert(...)` are not available in Prisma Client. - When you introspect a database that contains unsupported types, Prisma ORM will provide the following warning: ``` *** WARNING *** These fields are not supported by Prisma Client, because Prisma does not currently support their types. * Model "Post", field: "circle", original data type: "circle" ``` #### Examples ```prisma model Star { id Int @id @default(autoincrement()) position Unsupported("circle")? example1 Unsupported("circle") circle Unsupported("circle")? @default(dbgenerated("'<(10,4),11>'::circle")) } ``` ## `model` field type modifiers ### `[]` modifier Makes a field a list. #### Remarks - Cannot be optional (for example `Post[]?`). ##### Relational databases - Scalar lists (arrays) are only supported in the data model if your database natively supports them. Currently, scalar lists are therefore only supported when using PostgreSQL or CockroachDB (since MySQL and SQLite don't natively support scalar lists). ##### MongoDB - Scalar lists are supported #### Examples ##### Define a scalar list ```prisma highlight=3;normal model User { id Int @id @default(autoincrement()) //highlight-next-line favoriteColors String[] } ``` ```prisma highlight=3;normal model User { id String @id @default(auto()) @map("_id") @db.ObjectId //highlight-next-line favoriteColors String[] } ``` ##### Define a scalar list with a default value Available in version 4.0.0 and later. ```prisma highlight=3;normal model User { id Int @id @default(autoincrement()) //highlight-next-line favoriteColors String[] @default(["red", "blue", "green"]) } ``` ```prisma highlight=3;normal model User { id String @id @default(auto()) @map("_id") @db.ObjectId //highlight-next-line favoriteColors String[] @default(["red", "blue", "green"]) } ``` ### `?` modifier Makes a field optional. #### Remarks - Cannot be used with a list field (for example, `Posts[]`) #### Examples ##### Optional `name` field ```prisma highlight=3;normal model User { id Int @id @default(autoincrement()) //highlight-next-line name String? } ``` ## Attributes Attributes modify the behavior of a [field](#model-fields) or block (e.g. [models](#model)). There are two ways to add attributes to your data model: - _Field_ attributes are prefixed with `@` - _Block_ attributes are prefixed with `@@` Some attributes take arguments. Arguments in attributes are always named, but in most cases the argument _name_ can be omitted. > **Note**: The leading underscore in a signature means the _argument name_ can be omitted. ### `@id` Defines a single-field ID on the model. #### Remarks ##### General - Cannot be defined on a relation field - Cannot be optional ##### Relational databases - Corresponding database construct: `PRIMARY KEY` - Can be annotated with a [`@default`](#default) attribute that uses [functions](#attribute-functions) to auto-generate an ID: - [`autoincrement()`](#autoincrement) - [`cuid()`](#cuid) - [`uuid()`](#uuid) - [`ulid()`](#ulid) - Can be defined on any scalar field (`String`, `Int`, `enum`) ##### MongoDB - Corresponding database construct: [Any valid BSON type, except arrays](https://www.mongodb.com/docs/manual/core/document/#the-_id-field) - Every model must define an `@id` field - The [underlying ID field name is always `_id`](https://www.mongodb.com/docs/manual/core/document/#the-_id-field), and must be mapped with `@map("_id")` - Can be defined on any scalar field (`String`, `Int`, `enum`) unless you want to use `ObjectId` in your database - To use an [`ObjectId`](https://www.mongodb.com/docs/manual/reference/method/ObjectId/) as your ID, you must: - Use the `String` or `Bytes` field type - Annotate your field with `@db.ObjectId`: ```prisma id String @db.ObjectId @map("_id") ``` - Optionally, annotate your field with a [`@default`](#default) attribute that uses [the `auto()` function](#auto) to auto-generate an `ObjectId` ```prisma id String @db.ObjectId @map("_id") @default(auto()) ``` - [`cuid()`](#cuid), [`uuid()`](#uuid) and [`ulid()`](#ulid) are supported but do not generate a valid `ObjectId` - use `auto()` instead for `@id` - `autoincrement()` is **not supported** #### Arguments | Name | Required | Type | Description | | ----------- | -------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `map` | **No** | `String` | The name of the underlying primary key constraint in the database.

Not supported for MySQL or MongoDB. | | `length` | **No** | `number` | Allows you to specify a maximum length for the subpart of the value to be indexed.

MySQL only. In preview in versions 3.5.0 and later, and in general availability in versions 4.0.0 and later. | | `sort` | **No** | `String` | Allows you to specify in what order the entries of the ID are stored in the database. The available options are `Asc` and `Desc`.

SQL Server only. In preview in versions 3.5.0 and later, and in general availability in versions 4.0.0 and later. | | `clustered` | **No** | `Boolean` | Defines whether the ID is clustered or non-clustered. Defaults to `true`.

SQL Server only. In preview in versions 3.13.0 and later, and in general availability in versions 4.0.0 and later. | #### Signature ```prisma no-lines @id(map: String?, length: number?, sort: String?, clustered: Boolean?) ``` > **Note**: Before version 4.0.0, or 3.5.0 with the `extendedIndexes` Preview feature enabled, the signature was: > > ```prisma no-lines > @id(map: String?) > ``` > **Note**: Before version 3.0.0, the signature was: > > ```prisma no-lines > @id > ``` #### Examples In most cases, you want your database to create the ID. To do this, annotate the ID field with the `@default` attribute and initialize the field with a [function](#attribute-functions). ##### Generate autoincrementing integers as IDs (Relational databases only) ```prisma model User { id Int @id @default(autoincrement()) name String } ``` ##### Generate `ObjectId` as IDs (MongoDB only) ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId name String } ``` ##### Generate `cuid()` values as IDs ```prisma model User { id String @id @default(cuid()) name String } ``` ```prisma model User { id String @id @default(cuid()) @map("_id") name String } ``` You cannot use `cuid()` to generate a default value if your `id` field is of type `ObjectId`. Use the following syntax to generate a valid `ObjectId`: ```prisma id String @id @default(auto()) @db.ObjectId @map("_id") ``` ##### Generate `uuid()` values as IDs ```prisma model User { id String @id @default(uuid()) name String } ``` ```prisma model User { id String @id @default(uuid()) @map("_id") name String } ``` You cannot use `uuid()` to generate a default value if your `id` field is of type `ObjectId`. Use the following syntax to generate a valid `ObjectId`: ```prisma id String @id @default(auto()) @db.ObjectId @map("_id") ``` ##### Generate `ulid()` values as IDs ```prisma model User { id String @id @default(ulid()) name String } ``` ```prisma model User { id String @id @default(ulid()) @map("_id") name String } ``` You cannot use `ulid()` to generate a default value if your `id` field is of type `ObjectId`. Use the following syntax to generate a valid `ObjectId`: ```prisma id String @id @default(auto()) @db.ObjectId @map("_id") ``` ##### Single-field IDs _without_ default values In the following example, `id` does not have a default value: ```prisma model User { id String @id name String } ``` ```prisma model User { id String @id @map("_id") @db.ObjectId name String } ``` ```prisma model User { id String @id @map("_id") name String } ``` Note that in the above case, you _must_ provide your own ID values when creating new records for the `User` model using Prisma Client, e.g.: ```ts const newUser = await prisma.user.create({ data: { id: 1, name: "Alice", }, }); ``` ###### Specify an ID on relation scalar field without a default value In the following example, `authorId` is a both a relation scalar and the ID of `Profile`: ```prisma model Profile { authorId Int @id author User @relation(fields: [authorId], references: [id]) bio String } model User { id Int @id email String @unique name String? profile Profile? } ``` ```prisma model Profile { authorId String @id @map("_id") @db.ObjectId author User @relation(fields: [authorId], references: [id]) bio String } model User { id String @id @map("_id") @db.ObjectId email String @unique name String? profile Profile? } ``` In this scenario, you cannot create a `Profile` only - you must use Prisma Client's [nested writes](/orm/prisma-client/queries/relation-queries#nested-writes) create a `User` **or** connect the profile to an existing user. The following example creates a user and a profile: ```ts const userWithProfile = await prisma.user.create({ data: { id: 3, email: "bob@prisma.io", name: "Bob Prismo", profile: { create: { bio: "Hello, I'm Bob Prismo and I love apples, blue nail varnish, and the sound of buzzing mosquitoes.", }, }, }, }); ``` The following example connects a new profile to a user: ```ts const profileWithUser = await prisma.profile.create({ data: { bio: "Hello, I'm Bob and I like nothing at all. Just nothing.", author: { connect: { id: 22, }, }, }, }); ``` ### `@@id` **Not supported by MongoDB**
The [MongoDB connector](/orm/overview/databases/mongodb) does not support composite IDs.
Defines a multi-field ID (composite ID) on the model. #### Remarks - Corresponding database type: `PRIMARY KEY` - Can be annotated with a [`@default`](#default) attribute that uses [functions](#attribute-functions) to auto-generate an ID - Cannot be optional - Can be defined on any scalar field (`String`, `Int`, `enum`) - Cannot be defined on a relation field - The name of the composite ID field in Prisma Client has the following pattern: `field1_field2_field3` #### Arguments | Name | Required | Type | Description | | ----------- | -------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `fields` | **Yes** | `FieldReference[]` | A list of field names - for example, `["firstname", "lastname"]` | | `name` | **No** | `String` | The name that Prisma Client will expose for the argument covering all fields, e.g. `fullName` in `fullName: { firstName: "First", lastName: "Last"}` | | `map` | **No** | `String` | The name of the underlying primary key constraint in the database.

Not supported for MySQL. | | `length` | **No** | `number` | Allows you to specify a maximum length for the subpart of the value to be indexed.

MySQL only. In preview in versions 3.5.0 and later, and in general availability in versions 4.0.0 and later. | | `sort` | **No** | `String` | Allows you to specify in what order the entries of the ID are stored in the database. The available options are `Asc` and `Desc`.

SQL Server only. In preview in versions 3.5.0 and later, and in general availability in versions 4.0.0 and later. | | `clustered` | **No** | `Boolean` | Defines whether the ID is clustered or non-clustered. Defaults to `true`.

SQL Server only. In preview in versions 3.13.0 and later, and in general availability in versions 4.0.0 and later. | The name of the `fields` argument on the `@@id` attribute can be omitted: ```prisma no-lines @@id(fields: [title, author]) @@id([title, author]) ``` #### Signature ```prisma no-lines @@id(_ fields: FieldReference[], name: String?, map: String?) ``` > **Note**: Until version 3.0.0, the signature was: > > ```prisma no-lines > @@id(_ fields: FieldReference[]) > ``` #### Examples ##### Specify a multi-field ID on two `String` fields (Relational databases only) ```prisma model User { firstName String lastName String email String @unique isAdmin Boolean @default(false) @@id([firstName, lastName]) } ``` When you create a user, you must provide a unique combination of `firstName` and `lastName`: ```ts const user = await prisma.user.create({ data: { firstName: "Alice", lastName: "Smith", }, }); ``` To retrieve a user, use the generated composite ID field (`firstName_lastName`): ```ts const user = await prisma.user.findUnique({ where: { firstName_lastName: { firstName: "Alice", lastName: "Smith", }, }, }); ``` ##### Specify a multi-field ID on two `String` fields and one `Boolean` field (Relational databases only) ```prisma model User { firstName String lastName String email String @unique isAdmin Boolean @default(false) @@id([firstName, lastName, isAdmin]) } ``` When creating new `User` records, you now must provide a unique combination of values for `firstName`, `lastName` and `isAdmin`: ```ts const user = await prisma.user.create({ data: { firstName: "Alice", lastName: "Smith", isAdmin: true, }, }); ``` ##### Specify a multi-field ID that includes a relation field (Relational databases only) ```prisma model Post { title String published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int @@id([authorId, title]) } model User { id Int @default(autoincrement()) email String @unique name String? posts Post[] } ``` When creating new `Post` records, you now must provide a unique combination of values for `authorId` (foreign key) and `title`: ```ts const post = await prisma.post.create({ data: { title: "Hello World", author: { connect: { email: "alice@prisma.io", }, }, }, }); ``` ### `@default` Defines a [default value for a field](/orm/prisma-schema/data-model/models#defining-a-default-value). #### Remarks - Default values that cannot yet be represented in the Prisma schema are represented by the [`dbgenerated()` function](#dbgenerated) when you use [introspection](/orm/prisma-schema/introspection). - Default values are not allowed on relation fields in the Prisma schema. Note however that you can still define default values on the fields backing a relation (the ones listed in the `fields` argument in the `@relation` attribute). A default value on the field backing a relation will mean that relation is populated automatically for you. - Default values can be used with [scalar lists](/orm/prisma-client/special-fields-and-types/working-with-scalar-lists-arrays) in databases that natively support them. ##### Relational databases - Corresponding database construct: `DEFAULT` - Default values can be a static value (`4`, `"hello"`) or one of the following [functions](#attribute-functions): - [`autoincrement()`](#autoincrement) - [`sequence()`](#sequence) (CockroachDB only) - [`dbgenerated(...)`](#dbgenerated) - [`cuid()`](#cuid) - [`cuid(2)`](#cuid) - [`uuid()`](#uuid) - [`uuid(4)`](#uuid) - [`uuid(7)`](#uuid) - [`ulid()`](#ulid) - [`nanoid()`](#nanoid) - [`now()`](#now) - Default values that cannot yet be represented in the Prisma schema are represented by the [`dbgenerated(...)` function](#dbgenerated) when you use [introspection](/orm/prisma-schema/introspection). - Default values are not allowed on relation fields in the Prisma schema. Note however that you can still define default values on the fields backing a relation (the ones listed in the `fields` argument in the `@relation` attribute). A default value on the field backing a relation will mean that relation is populated automatically for you. - Default values can be used with [scalar lists](/orm/prisma-client/special-fields-and-types/working-with-scalar-lists-arrays) in databases that natively support them. - JSON data. Note that JSON needs to be enclosed with double-quotes inside the `@default` attribute, e.g.: `@default("[]")`. If you want to provide a JSON object, you need to enclose it with double-quotes and then escape any internal double quotes using a backslash, e.g.: `@default("{ \"hello\": \"world\" }")`. ##### MongoDB - Default values can be a static value (`4`, `"hello"`) or one of the following [functions](#attribute-functions): - [`auto()`](#auto) (can only be used with `@db.ObjectId` to generate an `ObjectId` in MongoDB) - [`cuid()`](#cuid) - [`uuid()`](#uuid) - [`ulid()`](#ulid) - [`now()`](#now) #### Arguments | Name | Required | Type | Description | | ------- | -------- | ----------------------------------------- | -------------------- | | `value` | **Yes** | An expression (e.g. `5`, `true`, `now()`) | | | `map` | **No** | String | **SQL Server only.** | The name of the `value` argument on the `@default` attribute can be omitted: ```prisma no-lines id Int @id @default(value: autoincrement()) id Int @id @default(autoincrement()) ``` #### Signature ```prisma no-lines @default(_ value: Expression, map: String?) ``` > **Note**: Until version 3.0.0, the signature was: > > ```prisma no-lines > @default(_ value: Expression) > ``` #### Examples ##### Default value for an `Int` ```prisma model User { email String @unique profileViews Int @default(0) } ``` ```prisma model User { id String @default(auto()) @map("_id") @db.ObjectId profileViews Int @default(0) } ``` ##### Default value for a `Float` ```prisma model User { email String @unique number Float @default(1.1) } ``` ```prisma model User { id String @default(auto()) @map("_id") @db.ObjectId number Float @default(1.1) } ``` ##### Default value for `Decimal` ```prisma model User { email String @unique number Decimal @default(22.99) } ``` [Not supported](https://github.com/prisma/prisma/issues/12637). ##### Default value for `BigInt` ```prisma model User { email String @unique number BigInt @default(34534535435353) } ``` ```prisma model User { id String @default(auto()) @map("_id") @db.ObjectId number BigInt @default(34534535435353) } ``` ##### Default value for a `String` ```prisma model User { email String @unique name String @default("") } ``` ```prisma model User { id String @default(auto()) @map("_id") @db.ObjectId name String @default("") } ``` ##### Default value for a `Boolean` ```prisma model User { email String @unique isAdmin Boolean @default(false) } ``` ```prisma model User { id String @default(auto()) @map("_id") @db.ObjectId isAdmin Boolean @default(false) } ``` ##### Default value for a `DateTime` Note that static default values for `DateTime` are based on the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) standard. ```prisma model User { email String @unique data DateTime @default("2020-03-19T14:21:00+02:00") } ``` ```prisma model User { id String @default(auto()) @map("_id") @db.ObjectId data DateTime @default("2020-03-19T14:21:00+02:00") } ``` ##### Default value for a `Bytes` ```prisma model User { email String @unique secret Bytes @default("SGVsbG8gd29ybGQ=") } ``` ```prisma model User { id String @default(auto()) @map("_id") @db.ObjectId secret Bytes @default("SGVsbG8gd29ybGQ=") } ``` ##### Default value for an `enum` ```prisma enum Role { USER ADMIN } ``` ```prisma highlight=5;normal model User { id Int @id @default(autoincrement()) email String @unique name String? //highlight-next-line role Role @default(USER) posts Post[] profile Profile? } ``` ```prisma enum Role { USER ADMIN } ``` ```prisma highlight=5;normal model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique name String? //highlight-next-line role Role @default(USER) posts Post[] profile Profile? } ``` ##### Default values for scalar lists ```prisma highlight=4;normal model User { id Int @id @default(autoincrement()) posts Post[] //highlight-next-line favoriteColors String[] @default(["red", "yellow", "purple"]) roles Role[] @default([USER, DEVELOPER]) } enum Role { USER DEVELOPER ADMIN } ``` ```prisma highlight=4;normal model User { id String @id @default(auto()) @map("_id") @db.ObjectId posts Post[] //highlight-next-line favoriteColors String[] @default(["red", "yellow", "purple"]) roles Role[] @default([USER, DEVELOPER]) } enum Role { USER DEVELOPER ADMIN } ``` ### `@unique` Defines a unique constraint for this field. #### Remarks ##### General - A field annotated with `@unique` can be optional or required - A field annotated with `@unique` _must_ be required if it represents the only unique constraint on a model without an `@id` / `@@id` - A model can have any number of unique constraints - Can be defined on any scalar field - **Cannot** be defined on a relation field ##### Relational databases - Corresponding database construct: `UNIQUE` - `NULL` values are considered to be distinct (multiple rows with `NULL` values in the same column are allowed) - Adding a unique constraint automatically adds a corresponding _unique index_ to the specified column(s). ##### MongoDB - Enforced by a [unique index in MongoDB](https://www.mongodb.com/docs/manual/core/index-unique/) #### Arguments | Name | Required | Type | Description | | ----------- | -------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `map` | **No** | `String` | | | `length` | **No** | `number` | Allows you to specify a maximum length for the subpart of the value to be indexed.

MySQL only. In preview in versions 3.5.0 and later, and in general availability in versions 4.0.0 and later. | | `sort` | **No** | `String` | Allows you to specify in what order the entries of the constraint are stored in the database. The available options are `Asc` and `Desc`.

In preview in versions 3.5.0 and later, and in general availability in versions 4.0.0 and later. | | `clustered` | **No** | `Boolean` | Defines whether the constraint is clustered or non-clustered. Defaults to `false`.

SQL Server only. In preview in versions 3.13.0 and later, and in general availability in versions 4.0.0 and later. | - ¹ Can be required by some of the index and field types. #### Signature ```prisma no-lines @unique(map: String?, length: number?, sort: String?) ``` > **Note**: Before version 4.0.0, or 3.5.0 with the `extendedIndexes` Preview feature enabled, the signature was: > > ```prisma no-lines > @unique(map: String?) > ``` > **Note**: Before version 3.0.0, the signature was: > > ```no-lines > @unique > ``` #### Examples ##### Specify a unique attribute on a required `String` field ```prisma model User { email String @unique name String } ``` ```prisma model User { id String @default(auto()) @map("_id") @db.ObjectId name String } ``` ##### Specify a unique attribute on an optional `String` field ```prisma model User { id Int @id @default(autoincrement()) email String? @unique name String } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String? @unique name String } ``` ##### Specify a unique attribute on relation scalar field `authorId` ```prisma model Post { author User @relation(fields: [authorId], references: [id]) authorId Int @unique title String published Boolean @default(false) } model User { id Int @id @default(autoincrement()) email String? @unique name String Post Post[] } ``` ```prisma model Post { author User @relation(fields: [authorId], references: [id]) authorId String @unique @db.ObjectId title String published Boolean @default(false) } model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String? @unique name String Post Post[] } ``` ##### Specify a unique attribute with `cuid()` values as default values ```prisma model User { token String @unique @default(cuid()) name String } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId token String @unique @default(cuid()) name String } ``` ### `@@unique` Defines a compound [unique constraint](/orm/prisma-schema/data-model/models#defining-a-unique-field) for the specified fields. #### Remarks ##### General - All fields that make up the unique constraint **must** be mandatory fields. The following model is **not** valid because `id` could be `null`: ```prisma model User { firstname Int lastname Int id Int? @@unique([firstname, lastname, id]) } ``` The reason for this behavior is that all connectors consider `null` values to be distinct, which means that two rows that _look_ identical are considered unique: ``` firstname | lastname | id -----------+----------+------ John | Smith | null John | Smith | null ``` - A model can have any number of `@@unique` blocks ##### Relational databases - Corresponding database construct: `UNIQUE` - A `@@unique` block is required if it represents the only unique constraint on a model without an `@id` / `@@id` - Adding a unique constraint automatically adds a corresponding _unique index_ to the specified column(s) ##### MongoDB - Enforced by a [compound index in MongoDB](https://www.mongodb.com/docs/manual/core/index-compound/) - A `@@unique` block cannot be used as the only unique identifier for a model - MongoDB requires an `@id` field #### Arguments | Name | Required | Type | Description | | ----------- | -------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `fields` | **Yes** | `FieldReference[]` | A list of field names - for example, `["firstname", "lastname"]`. Fields must be mandatory - see remarks. | | `name` | **No** | `String` | The name of the unique combination of fields - defaults to `fieldName1_fieldName2_fieldName3` | | `map` | **No** | `String` | | | `length` | **No** | `number` | Allows you to specify a maximum length for the subpart of the value to be indexed.

MySQL only. In preview in versions 3.5.0 and later, and in general availability in versions 4.0.0 and later. | | `sort` | **No** | `String` | Allows you to specify in what order the entries of the constraint are stored in the database. The available options are `Asc` and `Desc`.

In preview in versions 3.5.0 and later, and in general availability in versions 4.0.0 and later. | | `clustered` | **No** | `Boolean` | Defines whether the constraint is clustered or non-clustered. Defaults to `false`.

SQL Server only. In preview in versions 3.13.0 and later, and in general availability in versions 4.0.0 and later. | The name of the `fields` argument on the `@@unique` attribute can be omitted: ```prisma no-lines @@unique(fields: [title, author]) @@unique([title, author]) @@unique(fields: [title, author], name: "titleAuthor") ``` The `length` and `sort` arguments are added to the relevant field names: ```prisma no-lines @@unique(fields: [title(length:10), author]) @@unique([title(sort: Desc), author(sort: Asc)]) ``` #### Signature > ```prisma no-lines > @@unique(_ fields: FieldReference[], name: String?, map: String?) > ``` > **Note**: Before version 4.0.0, or before version 3.5.0 with the `extendedIndexes` Preview feature enabled, the signature was: > > ```prisma no-lines > @@unique(_ fields: FieldReference[], name: String?, map: String?) > ``` > **Note**: Before version 3.0.0, the signature was: > > ```prisma no-lines > @@unique(_ fields: FieldReference[], name: String?) > ``` #### Examples ##### Specify a multi-field unique attribute on two `String` fields ```prisma model User { id Int @default(autoincrement()) firstName String lastName String isAdmin Boolean @default(false) @@unique([firstName, lastName]) } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId firstName String lastName String isAdmin Boolean @default(false) @@unique([firstName, lastName]) } ``` To retrieve a user, use the generated field name (`firstname_lastname`): ```ts highlight=3;normal const user = await prisma.user.findUnique({ where: { firstName_lastName: { firstName: "Alice", lastName: "Smith", isAdmin: true, }, }, }); ``` ##### Specify a multi-field unique attribute on two `String` fields and one `Boolean` field ```prisma model User { id Int @default(autoincrement()) firstName String lastName String isAdmin Boolean @default(false) @@unique([firstName, lastName, isAdmin]) } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId firstName String lastName String isAdmin Boolean @default(false) @@unique([firstName, lastName, isAdmin]) } ``` ##### Specify a multi-field unique attribute that includes a relation field ```prisma model Post { id Int @default(autoincrement()) author User @relation(fields: [authorId], references: [id]) authorId Int title String published Boolean @default(false) @@unique([authorId, title]) } model User { id Int @id @default(autoincrement()) email String @unique posts Post[] } ``` ```prisma model Post { id String @id @default(auto()) @map("_id") @db.ObjectId author User @relation(fields: [authorId], references: [id]) authorId String @db.ObjectId title String published Boolean @default(false) @@unique([authorId, title]) } model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique posts Post[] } ``` ##### Specify a custom `name` for a multi-field unique attribute ```prisma model User { id Int @default(autoincrement()) firstName String lastName String isAdmin Boolean @default(false) @@unique(fields: [firstName, lastName, isAdmin], name: "admin_identifier") } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId firstName String lastName String isAdmin Boolean @default(false) @@unique(fields: [firstName, lastName, isAdmin], name: "admin_identifier") } ``` To retrieve a user, use the custom field name (`admin_identifier`): ```ts highlight=3;normal const user = await prisma.user.findUnique({ where: { admin_identifier: { firstName: "Alice", lastName: "Smith", isAdmin: true, }, }, }); ``` ### `@@index` Defines an index in the database. #### Remarks ##### Relational databases - Corresponding database construct: `INDEX` - There are some additional index configuration options that cannot be provided via the Prisma schema yet. These include: - PostgreSQL and CockroachDB: - Define index fields as expressions (e.g. `CREATE INDEX title ON public."Post"((lower(title)) text_ops);`) - Define partial indexes with `WHERE` - Create indexes concurrently with `CONCURRENTLY` While you cannot configure these option in your Prisma schema, you can still configure them on the database-level directly. ##### MongoDB - In version `3.12.0` and later, you can define an index on a field of a [composite type](/orm/prisma-schema/data-model/models#defining-composite-types) using the syntax `@@index([compositeType.field])`. See [Defining composite type indexes](/orm/prisma-schema/data-model/models#defining-composite-type-indexes) for more details. #### Arguments | Name | Required | Type | Description | | ----------- | -------- | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `fields` | **Yes** | `FieldReference[]` | A list of field names - for example, `["firstname", "lastname"]` | | `name` | **No** | `String` | The name that Prisma Client will expose for the argument covering all fields, e.g. `fullName` in `fullName: { firstName: "First", lastName: "Last"}` | | `map` | **No** | `map` | The name of the index in the underlying database (Prisma generates an index name that respects identifier length limits if you do not specify a name. Prisma uses the following naming convention: `tablename.field1_field2_field3_unique`) | | `length` | **No** | `number` | Allows you to specify a maximum length for the subpart of the value to be indexed.

MySQL only. In preview in versions 3.5.0 and later, and in general availability in versions 4.0.0 and later. | | `sort` | **No** | `String` | Allows you to specify in what order the entries of the index or constraint are stored in the database. The available options are `asc` and `desc`.

In preview in versions 3.5.0 and later, and in general availability in versions 4.0.0 and later. | | `clustered` | **No** | `Boolean` | Defines whether the index is clustered or non-clustered. Defaults to `false`.

SQL Server only. In preview in versions 3.5.0 and later, and in general availability in versions 4.0.0 and later. | | `type` | **No** | `identifier` | Allows you to specify an index access method. Defaults to `BTree`.

PostgreSQL and CockroachDB only. In preview with the `Hash` index access method in versions 3.6.0 and later, and with the `Gist`, `Gin`, `SpGist` and `Brin` methods added in 3.14.0. In general availability in versions 4.0.0 and later. | | `ops` | **No** | `identifier` or a `function` | Allows you to define the index operators for certain index types.

PostgreSQL only. In preview in versions 3.14.0 and later, and in general availability in versions 4.0.0 and later. | The _name_ of the `fields` argument on the `@@index` attribute can be omitted: ```prisma no-lines @@index(fields: [title, author]) @@index([title, author]) ``` The `length` and `sort` arguments are added to the relevant field names: ```prisma no-lines @@index(fields: [title(length:10), author]) @@index([title(sort: Asc), author(sort: Desc)]) ``` #### Signature ```prisma no-lines @@index(_ fields: FieldReference[], map: String?) ``` > **Note**: Until version 3.0.0, the signature was: > > ```prisma no-lines > @@index(_ fields: FieldReference[], name: String?) > ``` > > The old `name` argument will still be accepted to avoid a breaking change. #### Examples Assume you want to add an index for the `title` field of the `Post` model ##### Define a single-column index (Relational databases only) ```prisma model Post { id Int @id @default(autoincrement()) title String content String? @@index([title]) } ``` ##### Define a multi-column index (Relational databases only) ```prisma model Post { id Int @id @default(autoincrement()) title String content String? @@index([title, content]) } ``` ##### Define an index with a name (Relational databases only) ```prisma model Post { id Int @id @default(autoincrement()) title String content String? @@index(fields: [title, content], name: "main_index") } ``` ##### Define an index on a composite type field (Relational databases only) ```prisma type Address { street String number Int } model User { id Int @id email String address Address @@index([address.number]) } ``` ### `@relation` Defines meta information about the relation. [Learn more](/orm/prisma-schema/data-model/relations#the-relation-attribute). #### Remarks ##### Relational databases - Corresponding database constructs: `FOREIGN KEY` / `REFERENCES` ##### MongoDB - If your model's primary key is of type `ObjectId` in the underlying database, both the primary key _and_ the foreign key must have the `@db.ObjectId` attribute #### Arguments | Name | Type | Required | Description | Example | | :----------- | :--------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------- | | `name` | `String` | Sometimes (e.g. to disambiguate a relation) | Defines the name of the relationship. In an m-n-relation, it also determines the name of the underlying relation table. | `"CategoryOnPost"`, `"MyRelation"` | | `fields` | `FieldReference[]` | On [annotated](/orm/prisma-schema/data-model/relations#relation-fields) relation fields | A list of [fields](/orm/prisma-schema/data-model/models#defining-fields) of the _current_ model | `["authorId"]`, `["authorFirstName, authorLastName"]` | | `references` | `FieldReference[]` | On [annotated](/orm/prisma-schema/data-model/relations#relation-fields) relation fields | A list of [fields](/orm/prisma-schema/data-model/models#defining-fields) of the model on _the other side of the relation_ | `["id"]`, `["firstName, lastName"]` | | `map` | `String` | No | Defines a [custom name](/orm/prisma-schema/data-model/database-mapping#constraint-and-index-names) for the foreign key in the database. | `["id"]`, `["firstName, lastName"]` | | `onUpdate` | Enum. See [Types of referential actions](/orm/prisma-schema/data-model/relations/referential-actions#types-of-referential-actions) for values. | No | Defines the [referential action](/orm/prisma-schema/data-model/relations/referential-actions) to perform when a referenced entry in the referenced model is being updated. | `Cascade`, `NoAction` | | `onDelete` | Enum. See [Types of referential actions](/orm/prisma-schema/data-model/relations/referential-actions#types-of-referential-actions) for values. | No | Defines the [referential action](/orm/prisma-schema/data-model/relations/referential-actions) to perform when a referenced entry in the referenced model is being deleted. | `Cascade`, `NoAction` | The name of the `name` argument on the `@relation` attribute can be omitted (`references` is required): ```prisma @relation(name: "UserOnPost", references: [id]) @relation("UserOnPost", references: [id]) // or @relation(name: "UserOnPost") @relation("UserOnPost") ``` #### Signature ```prisma no-lines @relation(_ name: String?, fields: FieldReference[]?, references: FieldReference[]?, onDelete: ReferentialAction?, onUpdate: ReferentialAction?, map: String?) ``` With SQLite, the signature changes to: ```prisma no-lines @relation(_ name: String?, fields: FieldReference[]?, references: FieldReference[]?, onDelete: ReferentialAction?, onUpdate: ReferentialAction?) ``` > **Note**: Until version 3.0.0, the signature was: > > ```prisma no-lines > @relation(_ name: String?, fields: FieldReference[]?, references: FieldReference[]?) > ``` #### Examples See: [The `@relation` attribute](/orm/prisma-schema/data-model/relations#the-relation-attribute). ### `@map` Maps a field name or enum value from the Prisma schema to a column or document field with a different name in the database. If you do not use `@map`, the Prisma field name matches the column name or document field name exactly. > See [Using custom model and field names](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) to see how `@map` and `@@map` changes the generated Prisma Client. #### Remarks ##### General - `@map` **does not** rename the columns / fields in the database - `@map` **does** [change the field names in the generated client](#map-the-firstname-field-to-a-column-called-first_name) ##### MongoDB Your `@id` field must include `@map("_id")`. For example: ```prisma model User { id String @default(auto()) @map("_id") @db.ObjectId } ``` #### Arguments | Name | Type | Required | Description | Example | | :----- | :------- | :------- | :--------------------------------------------------------------------------- | :------------------------------ | | `name` | `String` | **Yes** | The database column (relational databases) or document field (MongoDB) name. | `"comments"`, `"someFieldName"` | The name of the `name` argument on the `@map` attribute can be omitted: ```prisma @map(name: "is_admin") @map("users") ``` #### Signature ```prisma no-lines @map(_ name: String) ``` #### Examples ##### Map the `firstName` field to a column called `first_name` ```prisma model User { id Int @id @default(autoincrement()) firstName String @map("first_name") } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId firstName String @map("first_name") } ``` The generated client: ```ts highlight=3;normal await prisma.user.create({ data: { firstName: "Yewande", // first_name --> firstName }, }); ``` ##### Map an enum named `ADMIN` to a database enum named `admin` ```prisma enum Role { ADMIN @map("admin") CUSTOMER } ``` ### `@@map` Maps the Prisma schema model name to a table (relational databases) or collection (MongoDB) with a different name, or an enum name to a different underlying enum in the database. If you do not use `@@map`, the model name matches the table (relational databases) or collection (MongoDB) name exactly. > See [Using custom model and field names](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) to see how `@map` and `@@map` changes the generated Prisma Client. #### Arguments | Name | Type | Required | Description | Example | | :----- | :------- | :------- | :---------------------------------------------------------------------- | :------------------------------------------ | | `name` | `String` | **Yes** | The database table (relational databases) or collection (MongoDB) name. | `"comments"`, `"someTableOrCollectionName"` | The name of the `name` argument on the `@@map` attribute can be omitted ```prisma @@map(name: "users") @@map("users") ``` #### Signature ```prisma no-lines @@map(_ name: String) ``` #### Examples ##### Map the `User` model to a database table/collection named `users` ```prisma model User { id Int @id @default(autoincrement()) name String @@map("users") } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId name String @@map("users") } ``` The generated client: ```ts highlight=1;normal await prisma.user.create({ // users --> user data: { name: "Yewande", }, }); ``` ##### Map the `Role` enum to a native enum in the database named `_Role` its values to lowercase values in the database ```prisma enum Role { ADMIN @map("admin") CUSTOMER @map("customer") @@map("_Role") } ``` ### `@updatedAt` Automatically stores the time when a record was last updated. If you do not supply a time yourself, Prisma Client will automatically set the value for fields with this attribute. #### Remarks - Compatible with [`DateTime`](#datetime) fields - Implemented at Prisma ORM level :::warning If you're also using [`now()`](/orm/reference/prisma-schema-reference#now), the time might differ from the `@updatedAt` values if your database and app have different timezones. This happens because `@updatedAt` operates at the Prisma ORM level, while `now()` operates at the database level. ::: :::note If you pass an empty update clause, the @updatedAt value will remain unchanged. For example: ```ts await prisma.user.update({ where: { id: 1, }, data: {}, //<- Empty update clause }); ``` ::: #### Arguments N/A #### Signature ```prisma no-lines @updatedAt ``` #### Examples ```prisma line-number model Post { id String @id updatedAt DateTime @updatedAt } ``` ```prisma line-number model Post { id String @id @map("_id") @db.ObjectId updatedAt DateTime @updatedAt } ``` ### `@ignore` Add `@ignore` to a field that you want to exclude from Prisma Client (for example, a field that you do not want Prisma Client users to update). Ignored fields are excluded from the generated Prisma Client. The model's `create` method is disabled when doing this for _required_ fields with no `@default` (because the database cannot create an entry without that data). #### Remarks - In [2.17.0](https://github.com/prisma/prisma/releases/tag/2.17.0) and later, Prisma ORM automatically adds `@ignore` to fields that _refer to_ invalid models when you introspect. #### Examples The following example demonstrates manually adding `@ignore` to exclude the `email` field from Prisma Client: ```prisma file=schema.prisma highlight=4;normal model User { id Int @id name String //highlight-next-line email String @ignore // this field will be excluded } ``` ### `@@ignore` Add `@@ignore` to a model that you want to exclude from Prisma Client (for example, a model that you do not want Prisma users to update). Ignored models are excluded from the generated Prisma Client. #### Remarks - In [2.17.0](https://github.com/prisma/prisma/releases/tag/2.17.0) and later, Prisma ORM adds `@@ignore` to an invalid model. (It also adds [`@ignore`](#ignore) to relations pointing to such a model) #### Examples In the following example, the `Post` model is invalid because it does not have a unique identifier. Use `@@ignore` to exclude it from the generated Prisma Client API: ```prisma file=schema.prisma highlight=7;normal /// The underlying table does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client. model Post { id Int @default(autoincrement()) // no unique identifier author User @relation(fields: [authorId], references: [id]) authorId Int //highlight-next-line @@ignore } ``` In the following example, the `Post` model is invalid because it does not have a unique identifier, and the `posts` relation field on `User` is invalid because it refers to the invalid `Post` model. Use `@@ignore` on the `Post` model and `@ignore` on the `posts` relation field in `User` to exclude both the model and the relation field from the generated Prisma Client API: ```prisma file=schema.prisma highlight=7,13;normal /// The underlying table does not contain a valid unique identifier and can therefore currently not be handled by Prisma Client. model Post { id Int @default(autoincrement()) // no unique identifier author User @relation(fields: [authorId], references: [id]) authorId Int //highlight-next-line @@ignore } model User { id Int @id @default(autoincrement()) name String? //highlight-next-line posts Post[] @ignore } ``` ### `@@schema` To use this attribute, you must have the [`multiSchema`](https://github.com/prisma/prisma/issues/1122#issuecomment-1231773471) preview feature enabled. Multiple database schema support is currently available with the PostgreSQL, CockroachDB, and SQL Server connectors. Add `@@schema` to a model to specify which schema in your database should contain the table associated with that model. #### Arguments | Name | Type | Required | Description | Example | | :----- | :------- | :------- | :------------------------------- | :----------------- | | `name` | `String` | **Yes** | The name of the database schema. | `"base"`, `"auth"` | The name of the `name` argument on the `@@schema` attribute can be omitted ```prisma @@schema(name: "auth") @@schema("auth") ``` #### Signature ```prisma no-lines @@schema(_ name: String) ``` #### Examples ##### Map the `User` model to a database schema named `auth` ```prisma highlight=3,9,16;normal generator client { provider = "prisma-client-js" //highlight-next-line previewFeatures = ["multiSchema"] } datasource db { provider = "postgresql" url = env("DATABASE_URL") //highlight-next-line schemas = ["auth"] } model User { id Int @id @default(autoincrement()) name String //highlight-next-line @@schema("auth") } ``` For more information about using the `multiSchema` feature, refer to [this guide](/orm/prisma-schema/data-model/multi-schema). ## Attribute functions ### `auto()` This function is available on MongoDB only. Represents **default values** that are automatically generated by the database. #### Remarks ##### MongoDB Used to generate an `ObjectId` for `@id` fields: ```prisma id String @map("_id") @db.ObjectId @default(auto()) ``` ##### Relational databases The `auto()` function is not available on relational databases. #### Example ##### Generate `ObjectId` (MongoDB only) ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId name String? } ``` ### `autoincrement()` **Not supported by MongoDB**
The [MongoDB connector](/orm/overview/databases/mongodb) does not support the `autoincrement()` function.
Create a sequence of integers in the underlying database and assign the incremented values to the ID values of the created records based on the sequence. #### Remarks - Compatible with `Int` on most databases (`BigInt` on CockroachDB) - Implemented on the database-level, meaning that it manifests in the database schema and can be recognized through introspection. Database implementations: | Database | Implementation | | ----------- | ------------------------------------------------------------------------------------------------- | | PostgreSQL | [`SERIAL`](https://www.postgresql.org/docs/9.1/datatype-numeric.html#DATATYPE-SERIAL) type | | MySQL | [`AUTO_INCREMENT`](https://dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html) attribute | | SQLite | [`AUTOINCREMENT`](https://www.sqlite.org/autoinc.html) keyword | | CockroachDB | [`SERIAL`](https://www.postgresql.org/docs/9.1/datatype-numeric.html#DATATYPE-SERIAL) type | #### Examples ##### Generate autoincrementing integers as IDs (Relational databases only) ```prisma model User { id Int @id @default(autoincrement()) name String } ``` ### `sequence()` **Only supported by CockroachDB**
The sequence function is only supported by [CockroachDB connector](/orm/overview/databases/cockroachdb).
Create a sequence of integers in the underlying database and assign the incremented values to the values of the created records based on the sequence. #### Optional arguments | Argument | Example | | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `virtual` | `@default(sequence(virtual))`
Virtual sequences are sequences that do not generate monotonically increasing values and instead produce values like those generated by the built-in function `unique_rowid()`. | | `cache` | `@default(sequence(cache: 20))`
The number of sequence values to cache in memory for reuse in the session. A cache size of `1` means that there is no cache, and cache sizes of less than `1` are not valid. | | `increment` | `@default(sequence(increment: 4))`
The new value by which the sequence is incremented. A negative number creates a descending sequence. A positive number creates an ascending sequence. | | `minValue` | `@default(sequence(minValue: 10))`
The new minimum value of the sequence. | | `maxValue` | `@default(sequence(maxValue: 3030303))`
The new maximum value of the sequence. | | `start` | `@default(sequence(start: 2))`
The value the sequence starts at, if it's restarted or if the sequence hits the `maxValue`. | #### Examples ##### Generate sequencing integers as IDs ```prisma model User { id Int @id @default(sequence(maxValue: 4294967295)) name String } ``` ### `cuid()` Generate a globally unique identifier based on the [`cuid`](https://github.com/ericelliott/cuid) spec. If you'd like to use [`cuid2`](https://github.com/paralleldrive/cuid2) values, you can pass `2` as an argument to the `cuid` function: `cuid(2)`. #### Remarks - Compatible with `String`. - Implemented by Prisma ORM and therefore not "visible" in the underlying database schema. You can still use `cuid()` when using [introspection](/orm/prisma-schema/introspection) by [manually changing your Prisma schema](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) and [generating Prisma Client](/orm/prisma-client/setup-and-configuration/generating-prisma-client), in that case the values will be generated by Prisma's [query engine](/orm/more/under-the-hood/engines). - Since the length of `cuid()` output is undefined per the cuid creator, a safe field size is 30 characters, in order to allow for enough characters for very large values. If you set the field size as less than 30, and then a larger value is generated by `cuid()`, you might see Prisma Client errors such as `Error: The provided value for the column is too long for the column's type.` - For **MongoDB**: `cuid()` does not generate a valid `ObjectId`. You can use [`@db.ObjectId` syntax](#generate-objectid-as-ids-mongodb-only) if you want to use `ObjectId` in the underlying database. However, you can still use `cuid()` if your `_id` field is not of type `ObjectId`. #### Examples ##### Generate `cuid()` values as IDs ```prisma model User { id String @id @default(cuid()) name String } ``` ```prisma model User { id String @id @default(cuid()) @map("_id") name String } ``` ##### Generate `cuid(2)` values as IDs based on the `cuid2` spec ```prisma model User { id String @id @default(cuid(2)) name String } ``` ```prisma model User { id String @id @default(cuid(2)) @map("_id") name String } ``` ### `uuid()` Generate a globally unique identifier based on the [UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) spec. Prisma ORM supports versions 4 (default) and 7. #### Remarks - Compatible with `String`. - Implemented by Prisma ORM and therefore not "visible" in the underlying database schema. You can still use `uuid()` when using [introspection](/orm/prisma-schema/introspection) by [manually changing your Prisma schema](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) and [generating Prisma Client](/orm/prisma-client/setup-and-configuration/generating-prisma-client), in that case the values will be generated by Prisma ORM's [query engine](/orm/more/under-the-hood/engines). - For **relational databases**: If you do not want to use Prisma ORM's `uuid()` function, you can use [the native database function with `dbgenerated`](#override-default-value-behavior-for-supported-types). - For **MongoDB**: `uuid()` does not generate a valid `ObjectId`. You can use [`@db.ObjectId` syntax](#generate-objectid-as-ids-mongodb-only) if you want to use `ObjectId` in the underlying database. However, you can still use `uuid()` if your `_id` field is not of type `ObjectId`. #### Examples ##### Generate `uuid()` values as IDs using UUID v4 ```prisma model User { id String @id @default(uuid()) name String } ``` ```prisma model User { id String @id @default(uuid()) @map("_id") name String } ``` ##### Generate `uuid(7)` values as IDs using UUID v7 ```prisma model User { id String @id @default(uuid(7)) name String } ``` ```prisma model User { id String @id @default(uuid(7)) @map("_id") name String } ``` ### `ulid()` Generate a universally unique lexicographically sortable identifier based on the [ULID](https://github.com/ulid/spec) spec. #### Remarks - `ulid()` will produce 128-bit random identifier represented as a 26-character long alphanumeric string, e.g.: `01ARZ3NDEKTSV4RRFFQ69G5FAV` #### Examples ##### Generate `ulid()` values as IDs ```prisma model User { id String @id @default(ulid()) name String } ``` ```prisma model User { id String @id @default(ulid()) @map("_id") name String } ``` ### `nanoid()` Generated values based on the [Nano ID](https://github.com/ai/nanoid) spec. `nanoid()` accepts an integer value between 2 and 255 that specifies the _length_ of the generate ID value, e.g. `nanoid(16)` will generated ID with 16 characters. If you don't provide a value to the nanoid() function, the default value is 21. :::info Nano ID is quite comparable to UUID v4 (random-based). It has a similar number of random bits in the ID (126 in Nano ID and 122 in UUID), so it has a similar collision probability: For there to be a one in a billion chance of duplication, 103 trillion version 4 IDs must be generated. There are two main differences between Nano ID and UUID v4: - Nano ID uses a bigger alphabet, so a similar number of random bits are packed in just 21 symbols instead of 36. - Nano ID code is 4 times smaller than uuid/v4 package: 130 bytes instead of 423. ::: #### Remarks - Compatible with `String`. - Implemented by Prisma ORM and therefore not "visible" in the underlying database schema. You can still use `uuid()` when using [introspection](/orm/prisma-schema/introspection) by [manually changing your Prisma schema](/orm/prisma-client/setup-and-configuration/custom-model-and-field-names) and [generating Prisma Client](/orm/prisma-client/setup-and-configuration/generating-prisma-client), in that case the values will be generated by Prisma ORM's [query engine](/orm/more/under-the-hood/engines). - For **MongoDB**: `nanoid()` does not generate a valid `ObjectId`. You can use [`@db.ObjectId` syntax](#generate-objectid-as-ids-mongodb-only) if you want to use `ObjectId` in the underlying database. However, you can still use `nanoid()` if your `_id` field is not of type `ObjectId`. #### Examples ##### Generate `nanoid()` values with 21 characters as IDs ```prisma model User { id String @id @default(nanoid()) name String } ``` ```prisma model User { id String @id @default(nanoid()) @map("_id") name String } ``` ##### Generate `nanoid()` values with 16 characters as IDs ```prisma model User { id String @id @default(nanoid(16)) name String } ``` ```prisma model User { id String @id @default(nanoid(16)) @map("_id") name String } ``` ### `now()` Set a timestamp of the time when a record is created. #### Remarks ##### General - Compatible with [`DateTime`](#datetime) :::warning If you're also using [`@updatedAt`](/orm/reference/prisma-schema-reference#updatedat), the time might differ from the `now()` values if your database and app have different timezones. This happens because `@updatedAt` operates at the Prisma ORM level, while `now()` operates at the database level. ::: ##### Relational databases - Implemented on the database-level, meaning that it manifests in the database schema and can be recognized through introspection. Database implementations: | Database | Implementation | | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | PostgreSQL | [`CURRENT_TIMESTAMP`](https://www.postgresql.org/docs/current/functions-datetime.html#FUNCTIONS-DATETIME-CURRENT) and aliases like `now()` | | MySQL | [`CURRENT_TIMESTAMP`](https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_current-timestamp) and aliases like `now()` | | SQLite | `CURRENT_TIMESTAMP` and aliases like `date('now')` | | CockroachDB | [`CURRENT_TIMESTAMP`](https://www.cockroachlabs.com/docs/stable/functions-and-operators#special-syntax-forms) and aliases like `now()` | ##### MongoDB - Implemented at Prisma ORM level #### Examples ##### Set current timestamp value when a record is created ```prisma model User { id String @id createdAt DateTime @default(now()) } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId createdAt DateTime @default(now()) } ``` ### `dbgenerated(...)` Represents **default values** that cannot be expressed in the Prisma schema (such as `random()`). #### Remarks ##### Relational databases - Compatible with any scalar type - Can not be an empty string `dbgenerated("")` in [2.21.0](https://github.com/prisma/prisma/releases/tag/2.21.0) and later - Accepts a `String` value in [2.17.0](https://github.com/prisma/prisma/releases/tag/2.17.0) and later, which allows you to: - [Set default values for `Unsupported` types](#set-default-value-for-unsupported-type) - [Override default value behavior for supported types](#override-default-value-behavior-for-supported-types) - String values in `dbgenerated(...)` might not match what the DB returns as the default value, because values such as strings may be explicitly cast (e.g. `'hello'::STRING`). When a mismatch is present, Prisma Migrate indicates a migration is still needed. You can use `prisma db pull` to infer the correct value to resolve the discrepancy. ([Related issue](https://github.com/prisma/prisma/issues/14917)) #### Examples ##### Set default value for `Unsupported` type ```prisma circle Unsupported("circle")? @default(dbgenerated("'<(10,4),11>'::circle")) ``` ##### Override default value behavior for supported types You can also use `dbgenerated(...)` to set the default value for supported types. For example, in PostgreSQL you can generate UUIDs at the database level rather than rely on Prisma ORM's `uuid()`: ```prisma highlight=2;add|3;delete model User { //add-next-line id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid //delete-next-line id String @id @default(uuid()) @db.Uuid test String? } ``` **Note**: [`gen_random_uuid()` is a PostgreSQL function](https://www.postgresql.org/docs/13/functions-uuid.html). To use it in PostgreSQL versions 12.13 and earlier, you must enable the `pgcrypto` extension.

In Prisma ORM versions 4.5.0 and later, you can declare the `pgcrypto` extension in your Prisma schema with the [`postgresqlExtensions` preview feature](/orm/prisma-schema/postgresql-extensions).
## Attribute argument types ### `FieldReference[]` An array of [field](#model-fields) names: `[id]`, `[firstName, lastName]` ### `String` A variable length text in double quotes: `""`, `"Hello World"`, `"Alice"` ### `Expression` An expression that can be evaluated by Prisma ORM: `42.0`, `""`, `Bob`, `now()`, `cuid()` ## `enum` **Not supported Microsoft SQL Server**
The [Microsoft SQL Server connector](/orm/overview/databases/sql-server) does not support the `enum` type.
Defines an [enum](/orm/prisma-schema/data-model/models#defining-enums) . ### Remarks - Enums are natively supported by [PostgreSQL](https://www.postgresql.org/docs/current/datatype-enum.html) and [MySQL](https://dev.mysql.com/doc/refman/8.0/en/enum.html) - Enums are implemented and enforced at Prisma ORM level in SQLite and MongoDB ### Naming conventions - Enum names must start with a letter (they are typically spelled in [PascalCase](http://wiki.c2.com/?PascalCase)) - Enums must use the singular form (e.g. `Role` instead of `role`, `roles` or `Roles`). - Must adhere to the following regular expression: `[A-Za-z][A-Za-z0-9_]*` ### Examples #### Specify an `enum` with two possible values ```prisma enum Role { USER ADMIN } model User { id Int @id @default(autoincrement()) role Role } ``` ```prisma enum Role { USER ADMIN } model User { id String @id @default(auto()) @map("_id") @db.ObjectId role Role } ``` #### Specify an `enum` with two possible values and set a default value ```prisma enum Role { USER ADMIN } model User { id Int @id @default(autoincrement()) role Role @default(USER) } ``` ```prisma enum Role { USER ADMIN } model User { id String @id @default(auto()) @map("_id") @db.ObjectId role Role @default(USER) } ``` ## `type` Composite types are available **for MongoDB only**. Composite types are available in versions 3.12.0 and later, and in versions 3.10.0 and later if you enable the `mongodb` Preview feature flag. Defines a [composite type](/orm/prisma-schema/data-model/models#defining-composite-types) . ### Naming conventions Type names must: - start with a letter (they are typically spelled in [PascalCase](http://wiki.c2.com/?PascalCase)) - adhere to the following regular expression: `[A-Za-z][A-Za-z0-9_]*` ### Examples #### Define a `Product` model with a list of `Photo` composite types ```prisma model Product { id String @id @default(auto()) @map("_id") @db.ObjectId name String photos Photo[] } type Photo { height Int width Int url String } ``` --- # Prisma CLI reference URL: https://www.prisma.io/docs/orm/reference/prisma-cli-reference This document describes the Prisma CLI commands, arguments, and options. ## Commands ### `version` (`-v`) The `version` command outputs information about your current `prisma` version, platform, and engine binaries. #### Options The `version` command recognizes the following options to modify its behavior: | Option | Required | Description | | -------- | -------- | ------------------------------------------- | | `--json` | No | Outputs version information in JSON format. | #### Examples ##### Output version information ```terminal prisma version ``` ```code no-copy Environment variables loaded from .env prisma : 2.21.0-dev.4 @prisma/client : 2.21.0-dev.4 Current platform : windows Query Engine : query-engine 2fb8f444d9cdf7c0beee7b041194b42d7a9ce1e6 (at C:\Users\veroh\AppData\Roaming\npm\node_modules\@prisma\cli\query-engine-windows.exe) Migration Engine : migration-engine-cli 2fb8f444d9cdf7c0beee7b041194b42d7a9ce1e6 (at C:\Users\veroh\AppData\Roaming\npm\node_modules\@prisma\cli\migration-engine-windows.exe) Format Binary : prisma-fmt 60ba6551f29b17d7d6ce479e5733c70d9c00860e (at node_modules\@prisma\engines\prisma-fmt-windows.exe) Default Engines Hash : 60ba6551f29b17d7d6ce479e5733c70d9c00860e Studio : 0.365.0 ``` ##### Output version information (`-v`) ```terminal prisma -v ``` ```code no-copy Environment variables loaded from .env prisma : 2.21.0-dev.4 @prisma/client : 2.21.0-dev.4 Current platform : windows Query Engine : query-engine 2fb8f444d9cdf7c0beee7b041194b42d7a9ce1e6 (at C:\Users\veroh\AppData\Roaming\npm\node_modules\@prisma\cli\query-engine-windows.exe) Migration Engine : migration-engine-cli 2fb8f444d9cdf7c0beee7b041194b42d7a9ce1e6 (at C:\Users\veroh\AppData\Roaming\npm\node_modules\@prisma\cli\migration-engine-windows.exe) Format Binary : prisma-fmt 60ba6551f29b17d7d6ce479e5733c70d9c00860e (at node_modules\@prisma\engines\prisma-fmt-windows.exe) Default Engines Hash : 60ba6551f29b17d7d6ce479e5733c70d9c00860e Studio : 0.365.0 ``` ##### Output version information as JSON ```terminal prisma version --json ``` ```code no-copy Environment variables loaded from .env { "prisma": "2.21.0-dev.4", "@prisma/client": "2.21.0-dev.4", "current-platform": "windows", "query-engine": "query-engine 60ba6551f29b17d7d6ce479e5733c70d9c00860e (at node_modules\\@prisma\\engines\\query-engine-windows.exe)", "migration-engine": "migration-engine-cli 60ba6551f29b17d7d6ce479e5733c70d9c00860e (at node_modules\\@prisma\\engines\\migration-engine-windows.exe)", "format-binary": "prisma-fmt 60ba6551f29b17d7d6ce479e5733c70d9c00860e (at node_modules\\@prisma\\engines\\prisma-fmt-windows.exe)", "default-engines-hash": "60ba6551f29b17d7d6ce479e5733c70d9c00860e", "studio": "0.365.0" } ``` ### `init` Bootstraps a fresh Prisma ORM project within the current directory. The `init` command does not interpret any existing files. Instead, it creates a `prisma` directory containing a bare-bones `schema.prisma` file within your current directory. #### Arguments | Argument | Required | Description | Default | | ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------- | | `--datasource-provider` | No | Specifies the value for the `provider` field in the `datasource` block. Options are `prisma+postgres`, `sqlite`, `postgresql`, `mysql`, `sqlserver`, `mongodb` and `cockroachdb`. | `postgresql` | | `--db` | No | Shorthand syntax for `--datasource-provider prisma+postgres`; creates a new [Prisma Postgres](/postgres) instance. Requires authentication in the [PDP Console](https://console.prisma.io). | | | `--prompt` (or `--vibe`) | No | Scaffolds a Prisma schema based on the prompt and deploys it to a fresh Prisma Postgres instance. Requires authentication in the [PDP Console](https://console.prisma.io). | | | `--url` | No | Define a custom datasource url. | | | `--generator-provider` | No | Define the generator provider to use. | `prisma-client-js` | | `--preview-feature` | No | Define the [Preview features](/orm/reference/preview-features) to use. To define multiple Preview features, you have to provide the flag multiple times for each Preview feature. See examples. | | | `--output` | No | Specifies the [output location for the generated client](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path). | `node_modules/.prisma/client` | | `--with-model` | No | Adds a simple `User` model to the initial Prisma schema. Available since version `5.14.0`. | | #### Examples **Run `prisma init`** ```terminal prisma init ``` ```code no-copy wrap ✔ Your Prisma schema was created at prisma/schema.prisma. You can now open it in your favorite editor. Next steps: 1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started 2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql, sqlite, sqlserver, mongodb or cockroachdb. 3. Run prisma db pull to turn your database schema into a Prisma schema. 4. Run prisma generate to generate Prisma Client. You can then start querying your database. More information in our documentation: https://pris.ly/d/getting-started ``` **Run `prisma init --datasource-provider sqlite`** ```terminal prisma init --datasource-provider sqlite ``` The command output contains helpful information on how to use the generated files and begin using Prisma ORM with your project. **Run `prisma init --db`** ```terminal prisma init --db ``` The command creates a new [Prisma Postgres](https://www.prisma.io/postgres) instance. Note that it requires you to be authenticated with the [PDP Console](https://console.prisma.io), If you run it for the first time without being authenticated, the command will open the browser for you to log into Console. **Run `prisma init --prompt "Simple habit tracker application"`** ```terminal prisma init --prompt "Simple habit tracker application" ``` The command scaffolds a Prisma schema and deploys it to a fresh [Prisma Postgres](https://www.prisma.io/postgres) instance. Note that it requires you to be authenticated with the [PDP Console](https://console.prisma.io), If you run it for the first time without being authenticated, the command will open the browser for you to log into Console. **Run `prisma init --preview-feature`** ```terminal prisma init --preview-feature multiSchema ``` ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" previewFeatures = ["multiSchema"] } ``` ```terminal prisma init --preview-feature multiSchema --preview-feature metrics ``` ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" previewFeatures = ["multiSchema", "metrics"] } ``` #### Generated Assets **`prisma/schema.prisma`** An initial `schema.prisma` file to define your schema in: ```prisma // This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema datasource db { provider = "sqlite" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } ``` **`.env`** A file to define environment variables for your project: ``` # Environment variables declared in this file are automatically made available to Prisma. # See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. # See the documentation for all the connection string options: https://pris.ly/d/connection-strings DATABASE_URL="file:./dev.db" ``` **Run `prisma init --url mysql://user:password@localhost:3306/mydb`** The `init` command with the `--url` argument allows you to specify a custom datasource URL during Prisma initialization, instead of relying on a placeholder database URL: ```terminal prisma init --url mysql://user:password@localhost:3306/mydb ``` #### Generated Assets **`prisma/schema.prisma`** A minimal `schema.prisma` file to define your schema in: ```prisma // This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema datasource db { provider = "mysql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } ``` **`.env`** A file to define environment variables for your project: ``` # Environment variables declared in this file are automatically made available to Prisma. # See the documentation for more detail: https://pris.ly/d/prisma-schema#using-environment-variables # Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB. # See the documentation for all the connection string options: https://pris.ly/d/connection-strings DATABASE_URL="mysql://user:password@localhost:3306/mydb" ``` ### `generate` The `generate` command generates assets like Prisma Client based on the [`generator`](/orm/prisma-schema/overview/generators) and [`data model`](/orm/prisma-schema/data-model/models) blocks defined in your `prisma/schema.prisma` file. The `generate` command is most often used to generate Prisma Client with the `prisma-client-js` generator. This does three things: 1. Searches the current directory and parent directories to find the applicable `npm` project. It will create a `package.json` file in the current directory if it cannot find one. 2. Installs the `@prisma/client` into the `npm` project if it is not already present. 3. Inspects the current directory to find a Prisma Schema to process. It will then generate a customized [Prisma Client](https://github.com/prisma/prisma-client-js) for your project. #### Prerequisites To use the `generate` command, you must add a generator definition in your `schema.prisma` file. The `prisma-client-js` generator, used to generate Prisma Client, can be added by including the following in your `schema.prisma` file: ```prisma generator client { provider = "prisma-client-js" } ``` #### Options | Option | Required | Description | Default | | ------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | | `--data-proxy` | No | The `generate` command will generate Prisma Client for use with [Prisma Accelerate](/accelerate) prior to Prisma 5.0.0. Mutually exclusive with `--accelerate` and `--no-engine`. | | `--accelerate` | No | The `generate` command will generate Prisma Client for use with [Prisma Accelerate](/accelerate). Mutually exclusive with `--data-proxy` and `--no-engine`. Available in Prisma 5.1.0 and later. | | `--no-engine` | No | The `generate` command will generate Prisma Client without an accompanied engine for use with [Prisma Accelerate](/accelerate). Mutually exclusive with `--data-proxy` and `--accelerate`. Available in Prisma ORM 5.2.0 and later. | | `--no-hints` | No | The `generate` command will generate Prisma Client without usage hints being printed to the terminal. Available in Prisma ORM 5.16.0 and later. | | `--allow-no-models` | No | The `generate` command will generate Prisma Client without generating any models. | | `--watch` | No | The `generate` command will continue to watch the `schema.prisma` file and re-generate Prisma Client on file changes. | **Deprecation Warning** As of Prisma 5.2.0, `--data-proxy` and `--accelerate` are deprecated in favor of `--no-engine` as Prisma Client no longer requires an option to work with Prisma Accelerate. All options are available and work similarly, but we recommend `--no-engine` as it prevents an engine from being downloaded which will greatly impact the size of apps deployed to serverless and edge functions. #### Arguments | Argument | Required | Description | Default | | | ------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | --- | | `--schema` | No | Specifies the path to the desired `schema.prisma` file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`, `./prisma/schema.prisma` | | | `--generator` | No | Specifies which generator to use to generate assets. This option may be provided multiple times to include multiple generators. By default, all generators in the target schema will be run. | | #### Examples ##### Generate Prisma Client using the default `schema.prisma` path ```terminal prisma generate ``` ```code no-copy ✔ Generated Prisma Client to ./node_modules/.prisma/client in 61ms You can now start using Prisma Client in your code: import { PrismaClient } from '@prisma/client' // or const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() Explore the full API: https://pris.ly/d/client ``` ##### Generate Prisma Client using a non-default `schema.prisma` path ```terminal prisma generate --schema=./alternative/schema.prisma ``` ##### Continue watching the `schema.prisma` file for changes to automatically re-generate Prisma Client ```terminal prisma generate --watch ``` ```code no-copy Watching... /home/prismauser/prisma/prisma-play/prisma/schema.prisma ✔ Generated Prisma Client to ./node_modules/.prisma/client in 45ms ``` ##### Run the `generate` command with only a specific generator ```terminal prisma generate --generator client ``` ##### Run the `generate` command with multiple specific generators ```terminal prisma generate --generator client --generator zod_schemas ``` #### Generated Assets The `prisma-client-js` generator creates a customized client for working with your database within the `./node_modules/.prisma/client` directory by default - you can [customize the output folder](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path). ### `validate` Validates the [Prisma Schema Language](/orm/prisma-schema) of the Prisma schema file. #### Arguments | Argument | Required | Description | Default | | ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | | `--schema` | No | Specifies the path to the desired `schema.prisma` file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`, `./prisma/schema.prisma` | #### Examples ##### Validate a schema without errors ```terminal prisma validate ``` ```code no-copy Environment variables loaded from .env Prisma schema loaded from prisma/schema.prisma The schema at /absolute/path/prisma/schema.prisma is valid 🚀 ``` ##### Validate a schema with validation errors ```terminal prisma validate ``` ```code no-copy Environment variables loaded from .env Prisma schema loaded from prisma/schema.prisma Error: Schema validation error - Error (query-engine-node-api library) Error code: P1012 error: The preview feature "unknownFeatureFlag" is not known. Expected one of: [...] --> schema.prisma:3 | 2 | provider = "prisma-client-js" 3 | previewFeatures = ["unknownFeatureFlag"] | Validation Error Count: 1 [Context: getDmmf] Prisma CLI Version : 4.5.0 ``` ### `format` Formats the Prisma schema file, which includes validating, formatting, and persisting the schema. #### Arguments | Argument | Required | Description | Default | | ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | | `--schema` | No | Specifies the path to the desired `schema.prisma` file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`, `./prisma/schema.prisma` | | `--check` | No | Fails if any files are unformatted. This can be used in CI to detect if the schema is formatted correctly | | #### Examples ##### Validate a schema without errors ```terminal prisma format ``` ```code no-copy Environment variables loaded from .env Prisma schema loaded from prisma/schema.prisma Formatted prisma/schema.prisma in 116ms � ``` ##### Formatting a schema with validation errors ```terminal prisma format ``` ```code no-copy Environment variables loaded from .env Prisma schema loaded from prisma/schema.prisma Error: Schema validation error - Error (query-engine-node-api library) Error code: P1012 error: The preview feature "unknownFeatureFlag" is not known. Expected one of: [...] --> schema.prisma:3 | 2 | provider = "prisma-client-js" 3 | previewFeatures = ["unknownFeatureFlag"] | Validation Error Count: 1 [Context: getDmmf] Prisma CLI Version : 4.5.0 ``` ### `debug` Prints information for debugging and bug reports. :::info This is available from version 5.6.0 and newer. ::: #### Arguments | Argument | Required | Description | Default | | ---------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | | `--schema` | No | Specifies the path to the desired `schema.prisma` file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`, `./prisma/schema.prisma` | | `--help` / `--h` | No | Displays the help message | | #### Example ```terminal prisma debug ``` ```text no-copy -- Prisma schema -- Path: /prisma/schema.prisma -- Local cache directory for engines files -- Path: /.cache/prisma -- Environment variables -- When not set, the line is dimmed and no value is displayed. When set, the line is bold and the value is inside the `` backticks. For general debugging - CI: - DEBUG: - NODE_ENV: - RUST_LOG: - RUST_BACKTRACE: - NO_COLOR: - TERM: `xterm-256color` - NODE_TLS_REJECT_UNAUTHORIZED: - NO_PROXY: - http_proxy: - HTTP_PROXY: - https_proxy: - HTTPS_PROXY: For more information see our [environment variable documentation](/orm/reference/environment-variables-reference) For hiding messages - PRISMA_DISABLE_WARNINGS: - PRISMA_HIDE_PREVIEW_FLAG_WARNINGS: - PRISMA_HIDE_UPDATE_MESSAGE: For downloading engines - PRISMA_ENGINES_MIRROR: - PRISMA_BINARIES_MIRROR (deprecated): - PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING: - BINARY_DOWNLOAD_VERSION: For configuring the Query Engine Type - PRISMA_CLI_QUERY_ENGINE_TYPE: - PRISMA_CLIENT_ENGINE_TYPE: For custom engines - PRISMA_QUERY_ENGINE_BINARY: - PRISMA_QUERY_ENGINE_LIBRARY: - PRISMA_SCHEMA_ENGINE_BINARY: - PRISMA_MIGRATION_ENGINE_BINARY: For the "postinstall" npm hook - PRISMA_GENERATE_SKIP_AUTOINSTALL: - PRISMA_SKIP_POSTINSTALL_GENERATE: - PRISMA_GENERATE_IN_POSTINSTALL: For "prisma generate" - PRISMA_GENERATE_DATAPROXY: - PRISMA_GENERATE_NO_ENGINE: For Prisma Client - PRISMA_SHOW_ALL_TRACES: - PRISMA_CLIENT_NO_RETRY (Binary engine only): For Prisma Migrate - PRISMA_SCHEMA_DISABLE_ADVISORY_LOCK: - PRISMA_MIGRATE_SKIP_GENERATE: - PRISMA_MIGRATE_SKIP_SEED: For Prisma Studio - BROWSER: -- Terminal is interactive? -- true -- CI detected? -- false ``` If you're using an older version of Prisma, you can use this command by running: ```terminal npx prisma@latest debug ``` ## `db` ### `db pull` The `db pull` command connects to your database and adds Prisma models to your Prisma schema that reflect the current database schema. **Warning**: The command will overwrite the current `schema.prisma` file with the new schema. Some manual changes or customization can be lost. Be sure to back up your current `schema.prisma` file (or commit your current state to version control to be able to revert any changes) before running `db pull` if it contains important modifications. Introspection with the `db pull` command on the [MongoDB connector](/orm/overview/databases/mongodb) samples the data instead of reading a schema. #### Prerequisites Before using the `db pull` command, you must define a valid [`datasource`](/orm/prisma-schema/overview/data-sources) within your `schema.prisma` file. For example, the following `datasource` defines a SQLite database file within the current directory: ```prisma datasource db { provider = "sqlite" url = "file:my-database.db" } ``` #### Options | Option | Required | Description | Default | | --------- | -------- | --------------------------------------------------------------------------------------------------------------------- | ------- | | `--force` | No | Force overwrite of manual changes made to schema. The generated schema will be based on the introspected schema only. | | `--print` | No | Prints the created `schema.prisma` to the screen instead of writing it to the filesystem. | #### Arguments | Argument | Required | Description | Default | | ---------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------- | | `--schema` | No | Specifies the path to the desired `schema.prisma` file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`, `./prisma/schema.prisma` | #### Examples ##### Analyze the database and write its schema to the `schema.prisma` file ```terminal prisma db pull ``` ```code no-copy Introspecting based on datasource defined in schema.prisma … ✔ Introspected 2 models and wrote them into schema.prisma in 38ms Run prisma generate to generate Prisma Client. ``` ##### Specify an alternative `schema.prisma` file to read and write to ```terminal prisma db pull --schema=./alternative/schema.prisma ``` ```code no-copy Introspecting based on datasource defined in alternative/schema.prisma … ✔ Introspected 2 models and wrote them into alternative/schema.prisma in 60ms Run prisma generate to generate Prisma Client. ``` ##### Display the generated `schema.prisma` file instead of writing it to the filesystem ```terminal prisma db pull --print ``` ```prisma no-copy generator client { provider = "prisma-client-js" } datasource db { provider = "sqlite" url = "file:./hello-prisma.db" } model User { email String @unique name String? user_id Int @id @default(autoincrement()) post Post[] profile Profile[] } model Post { content String? post_id Int @id @default(autoincrement()) title String author User? @relation(fields: [author_id], references: [user_id]) author_id Int? } model Profile { bio String? profile_id Int @id @default(autoincrement()) user User @relation(fields: [user_id], references: [user_id]) user_id Int @unique } ``` ### `db push` The `db push` command pushes the state of your Prisma schema to the database without using migrations. It creates the database if the database does not exist. This command is a good choice when you do not need to version schema changes, such as during prototyping and local development. See also: - [Conceptual overview of `db push` and when to use it over Prisma Migrate](/orm/prisma-migrate/workflows/prototyping-your-schema) - [Schema prototyping with `db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) #### Prerequisites Before using the `db push` command, you must define a valid [datasource](/orm/prisma-schema/overview/data-sources) within your `schema.prisma` file. For example, the following `datasource` defines a SQLite database file within the current directory: ```prisma datasource db { provider = "sqlite" url = "file:my-database.db" } ``` #### Options | Options | Required | Description | | :------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------- | | `--skip-generate` | No | Skip generation of artifacts such as Prisma Client | | `--force-reset` | No | Resets the database and then updates the schema - useful if you need to start from scratch due to unexecutable migrations. | | `--accept-data-loss` | No | Ignore data loss warnings. This option is required if as a result of making the schema changes, data may be lost. | | `--help` / `--h` | No | Displays the help message | #### Arguments | Argument | Required | Description | Default | | :--------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | | `--schema` | No | Specifies the path to the desired schema.prisma file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`
`./prisma/schema.prisma` | #### Examples Push the schema: ```terminal prisma db push ``` Push the schema, accepting data loss: ```terminal prisma db push --accept-data-loss ``` Push the schema with a custom schema location: ```terminal prisma db push --schema=/tmp/schema.prisma ``` ### `db seed` `db seed` changed from Preview to Generally Available (GA) in 3.0.1. See [Seeding your database](/orm/prisma-migrate/workflows/seeding) #### Options | Options | Required | Description | | :--------------- | :------- | :-------------------------------------------------------- | | `--help` / `--h` | No | Displays the help message | | `--` | No | Allows the use of custom arguments defined in a seed file | The `--` argument/ [delimiter](https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html#tag_12_02)/ double-dash is available from version 4.15.0 or later. #### Examples ```terminal prisma db seed ``` ### `db execute` The `db execute` command is Generally Available in versions 3.13.0 and later. If you're using a version between 3.9.0 and 3.13.0, it is available behind a `--preview-feature` CLI flag. This command is currently not supported on [MongoDB](/orm/overview/databases/mongodb). This command applies a SQL script to the database without interacting with the Prisma migrations table. The script takes two inputs: - the SQL script, which can be provided either on standard input or in a file - the data source, which can either be the URL of the data source or the path to your Prisma schema file The output of the command is connector-specific, and is not meant for returning data, but only to report success or failure. See also: - [Migration troubleshooting in production](/orm/prisma-migrate/workflows/patching-and-hotfixing#fixing-failed-migrations-with-migrate-diff-and-db-execute) #### Prerequisites Before using the `db execute` command, if you do not use the `--url` option you must define a valid [`datasource`](/orm/prisma-schema/overview/data-sources) within your `schema.prisma` file. For example, the following `datasource` defines a SQLite database file within the current directory: ```prisma datasource db { provider = "sqlite" url = "file:my-database.db" } ``` #### Options One of the following data source inputs is required: | Options | Description | | :--------- | :------------------------------------------------------------------- | | `--url` | URL of the data source to run the command on | | `--schema` | Path to a Prisma schema file, uses the URL in the `datasource` block | One of the following script inputs is required: | Options | Description | | :-------- | :-------------------------------------------------------------------- | | `--stdin` | Use the terminal standard input as the script to be executed | | `--file` | Path to a file. The content will be sent as the script to be executed | Other options: | Options | Required | Description | | :------- | :------- | :------------------------- | | `--help` | No | Displays the help message. | #### Examples - Take the content of a SQL file located at `./script.sql` and execute it on the database specified by the URL in the `datasource` block of your `schema.prisma` file: ```terminal prisma db execute --file ./script.sql --schema schema.prisma ``` - Take the SQL script from standard input and execute it on the database specified by the data source URL given in the `DATABASE_URL` environment variable: ```terminal wrap echo 'TRUNCATE TABLE dev;' | prisma db execute --stdin --url="$DATABASE_URL" ``` ## Prisma Migrate Prisma Migrate changed from Preview to Generally Available (GA) in 2.19.0. **Does not apply for MongoDB**
Instead of `migrate dev` and related commands, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb).
### `migrate dev` **For use in development environments only, requires shadow database** The `migrate dev` command: 1. Reruns the existing migration history in the [shadow database](/orm/prisma-migrate/understanding-prisma-migrate/shadow-database) in order to detect schema drift (edited or deleted migration file, or a manual changes to the database schema) 1. Applies pending migrations to the shadow database (for example, new migrations created by colleagues) 1. Generates a new migration from any changes you made to the Prisma schema before running `migrate dev` 1. Applies all unapplied migrations to the development database and updates the `_prisma_migrations` table 1. Triggers the generation of artifacts (for example, Prisma Client) This command is not supported on [MongoDB](/orm/overview/databases/mongodb). Use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) instead. See also: - [Conceptual overview of Prisma Migrate](/orm/prisma-migrate) - [Developing with Prisma Migrate](/orm/prisma-migrate) #### Options | Option | Required | Description | Default | | :---------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :------ | | `--create-only` | No | Creates a new migration but does not apply it. This also works if you haven't made any changes to your schema (in that case, an empty migration is created). Run `migrate dev` to apply migration. | | | `--skip-seed` | No | Skip triggering seed | | | `--skip-generate` | No | Skip triggering generators (for example, Prisma Client) | | | `--name` / `-n` | No | Name the migration (e.g. `prisma migrate dev --name added_job_title`) | | | `--help` / `-h` | No | Displays the help message | | If a [schema drift](/orm/prisma-migrate/understanding-prisma-migrate/shadow-database#detecting-schema-drift) is detected while running `prisma migrate dev` using `--create-only`, you will be prompted to reset your database. #### Arguments | Argument | Required | Description | Default | | :--------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | | `--name` | No | The name of the migration. If no name is provided, the CLI will prompt you. | | | `--schema` | No | Specifies the path to the desired schema.prisma file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`
`./prisma/schema.prisma` | #### Examples Apply all migrations, then create and apply any new migrations: ```terminal prisma migrate dev ``` Apply all migrations and create a new migration if there are schema changes, but do not apply it: ```terminal prisma migrate dev --create-only ``` ### `migrate reset` **For use in development environments only** This command: 1. Drops the database/schema if possible, or performs a soft reset if the environment does not allow deleting databases/schemas 1. Creates a new database/schema with the same name if the database/schema was dropped 1. Applies all migrations 1. Runs seed scripts This command is not supported on [MongoDB](/orm/overview/databases/mongodb). Use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) instead. #### Options | Option | Required | Description | Default | | :---------------- | :------- | :------------------------------------------------------ | :------ | | `--force` | No | Skip the confirmation prompt | | | `--skip-generate` | No | Skip triggering generators (for example, Prisma Client) | | | `--skip-seed` | No | Skip triggering seed | | | `--help` / `--h` | No | Displays the help message | #### Arguments | Argument | Required | Description | Default | | :--------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | | `--schema` | No | Specifies the path to the desired schema.prisma file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`
`./prisma/schema.prisma` | #### Examples ```terminal prisma migrate reset ``` ### `migrate deploy` The `migrate deploy` command applies all pending migrations, and creates the database if it does not exist. Primarily used in non-development environments. This command: - Does **not** look for drift in the database or changes in the Prisma schema - Does **not** reset the database or generate artifacts - Does **not** rely on a shadow database This command is not supported on [MongoDB](/orm/overview/databases/mongodb). Use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) instead. #### Options | Option | Required | Description | Default | | :--------------- | :------- | :------------------------ | :------ | | `--help` / `--h` | No | Displays the help message | #### Arguments | Argument | Required | Description | Default | | :--------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | | `--schema` | No | Specifies the path to the desired schema.prisma file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`
`./prisma/schema.prisma` | #### Examples ```terminal prisma migrate deploy ``` ### `migrate resolve` The `migrate resolve` command allows you to solve migration history issues in production by marking a failed migration as already applied (supports baselining) or rolled back. Note that this command can only be used with a failed migration. If you try to use it with a successful migration you will receive an error. This command is not supported on [MongoDB](/orm/overview/databases/mongodb). Use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) instead. #### Options | Option | Required | Description | Default | | :--------------- | :------- | :------------------------ | :------ | | `--help` / `--h` | No | Displays the help message | #### Arguments | Argument | Required | Description | Default | | :-------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | | `--applied` | No\* | Record a specific migration as applied - for example `--applied "20201231000000_add_users_table"` | | | `--rolled-back` | No\* | Record a specific migration as rolled back - for example `--rolled-back "20201231000000_add_users_table"` | `./schema.prisma`
`./prisma/schema.prisma` | | `--schema` | No | Specifies the path to the desired schema.prisma file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`
`./prisma/schema.prisma` | You must specify either `--rolled-back` _or_ `--applied`. #### Examples ```terminal prisma migrate resolve --applied 20201231000000_add_users_table ``` ```terminal prisma migrate resolve --rolled-back 20201231000000_add_users_table ``` ### `migrate status` The `prisma migrate status` command looks up the migrations in `./prisma/migrations/*` folder and the entries in the `_prisma_migrations` table and compiles information about the state of the migrations in your database. This command is not supported on [MongoDB](/orm/overview/databases/mongodb). Use [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) instead. For example: ``` Status 3 migrations found in prisma/migrations Your local migration history and the migrations table from your database are different: The last common migration is: 20201127134938_new_migration The migration have not yet been applied: 20201208100950_test_migration The migrations from the database are not found locally in prisma/migrations: 20201208100950_new_migration ``` In versions 4.3.0 and later, `prisma migrate status` exits with exit code 1 in the following cases: - a database connection error occurs - there are migration files in the `migrations` directory that have not been applied to the database - the migration history in the `migrations` directory has diverged from the state of the database - no migration table is found - failed migrations are found #### Options | Option | Required | Description | Default | | :--------------- | :------- | :------------------------ | :------ | | `--help` / `--h` | No | Displays the help message | #### Arguments | Argument | Required | Description | Default | | :--------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | | `--schema` | No | Specifies the path to the desired schema.prisma file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`
`./prisma/schema.prisma` | #### Examples ```terminal prisma migrate status ``` ### `migrate diff` :::info This command is only partially supported for [MongoDB](/orm/overview/databases/mongodb). See the command options below for details. ::: This command compares two database schema sources and outputs a description of a migration taking the first to the state of the second. The output can be given either as a human-readable summary (the default) or an executable script. :::warning The `migrate diff` command can only compare database features that are [supported by Prisma](/orm/reference/database-features). If two databases differ only in unsupported features, such as views or triggers, then `migrate diff` will not show any difference between them. ::: The format of the command is: ```terminal prisma migrate diff --from-... --to-... ``` where the `--from-...` and `--to-...` options are selected based on the type of database schema source. The supported types of sources are: - live databases - migration histories - Prisma schema data models - an empty schema Both schema sources must use the same database provider. For example, a diff comparing a PostgreSQL data source with a SQLite data source is not supported. See also: - [Migration troubleshooting in production](/orm/prisma-migrate/workflows/patching-and-hotfixing#fixing-failed-migrations-with-migrate-diff-and-db-execute) #### Prerequisites Before using the `migrate diff` command, if you are using the `--from-schema-datasource` or `--to-schema-datasource` you must define a valid [`datasource`](/orm/prisma-schema/overview/data-sources) within your `schema.prisma` file. For example, the following `datasource` defines a SQLite database file within the current directory: ```prisma datasource db { provider = "sqlite" url = "file:my-database.db" } ``` #### Options One of the following `--from-...` options is required: | Options | Description | Notes | | :------------------------- | :---------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------- | | `--from-url` | A data source URL | | | `--from-migrations` | Path to the Prisma Migrate migrations directory | Not supported in MongoDB | | `--from-schema-datamodel` | Path to a Prisma schema file, uses the data model for the diff | | | `--from-schema-datasource` | Path to a Prisma schema file, uses the URL in the `datasource` block for the diff | | | `--from-empty` | Assume that you the data model you are migrating from is empty | | | `--from-local-d1` | Path to a local D1 instance ([learn more](/orm/overview/databases/cloudflare-d1#using-the-wrangler-cli)) | Available since [5.12.0](https://github.com/prisma/prisma/releases/tag/5.12.0) | One of the following `--to-...` options is required: | Options | Description | Notes | | :----------------------- | :---------------------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------- | | `--to-url` | A data source URL | | | `--to-migrations` | Path to the Prisma Migrate migrations directory | Not supported in MongoDB | | `--to-schema-datamodel` | Path to a Prisma schema file, uses the data model for the diff | | | `--to-schema-datasource` | Path to a Prisma schema file, uses the URL in the `datasource` block for the diff | | | `--to-empty` | Assume that you the data model you are migrating to is empty | | | `--to-local-d1` | Path to a local D1 instance ([learn more](/orm/overview/databases/cloudflare-d1#using-the-wrangler-cli)) | Available since [5.12.0](https://github.com/prisma/prisma/releases/tag/5.12.0) | Other options: | Options | Required | Description | Notes | | :---------------------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------- | | `--shadow-database-url` | No | URL for the shadow database | Only required if using `--to-migrations` or `--from-migrations` | | `--script` | No | Outputs a SQL script instead of the default human-readable summary | Not supported in MongoDB | | `-o`, `--output` | No | Writes to a file instead of stdout | Available since [5.12.1](https://github.com/prisma/prisma/releases/tag/5.12.1) | | `--exit-code` | No | Change the exit code behavior to signal if the diff is empty or not (Empty: 0, Error: 1, Not empty: 2). Default behavior is Success: 0, Error: 1. | | | `--help` | No | Displays the help message. | | #### Examples - Compare two databases specified by their data source URL, and output the default human-readable summary: ```terminal prisma migrate diff \ --from-url "$DATABASE_URL" \ --to-url "postgresql://login:password@localhost:5432/db2" ``` - Compare the state of a database with a URL of `$DATABASE_URL` to the schema defined by the migrations in the `./prisma/migrations` directory, and output the differences to a script `script.sql`: ```terminal prisma migrate diff \ --from-url "$DATABASE_URL" \ --to-migrations ./prisma/migrations \ --shadow-database-url $SHADOW_DATABASE_URL \ --script > script.sql ``` ## Prisma Data Platform ### `platform` ([Early Access](/platform/maturity-levels#early-access)) The `platform` command provides access to the Prisma Data Platform through the Prisma CLI starting in version `5.10.0` or later. - **Authentication**: - `platform auth login`: Opens a browser window for login or account creation. - `platform auth logout`: Logs out of the platform. - `platform auth show`: Displays information about the currently authenticated user. - **Workspace Management**: - `platform workspace show`: Lists all workspaces available to your account. - **Project Management**: - `platform project show`: Lists all projects within the specified workspace. - `platform project create`: Creates a new project within the specified workspace. - `platform project delete`: Deletes the specified project. - **Environment Management**: - `platform environment show`: Lists all environments for the specified project. - `platform environment create`: Creates a new environment within the specified project. - `platform environment delete`: Deletes the specified environment. - **API Key Management**: - `platform apikey show`: Lists all API keys for the specified environment. - `platform apikey create`: Creates a new API key for the specified environment. - `platform apikey delete`: Deletes the specified API key. - **Prisma Accelerate**: - `platform accelerate enable`: Enables Prisma Accelerate for the specified environment. - `platform accelerate disable`: Disables Prisma Accelerate for the specified environment. You can find the complete list of available commands with the arguments [here](/platform/platform-cli/commands). ### `mcp` Starts the [Prisma MCP server](/postgres/mcp-server). ## Studio ### `studio` The `studio` command allows you to interact with and manage your data interactively. It does this by starting a local web server with a web app configured with your project's data schema and records. #### Prerequisites Before using the `studio` command, you must define a valid [`datasource`](/orm/prisma-schema/overview/data-sources) within your `schema.prisma` file. For example, the following `datasource` defines a SQLite database file within the current directory: ```prisma datasource db { provider = "sqlite" url = "file:my-database.db" } ``` #### Options The `studio` command recognizes the following options: | Option | Required | Description | Default | | ----------------- | -------- | ----------------------------------- | ------------------------ | | `-b`, `--browser` | No | The browser to auto-open Studio in. | `` | | `-h`, `--help` | No | Show all available options and exit | | | `-p`, `--port` | No | The port number to start Studio on. | 5555 | #### Arguments | Argument | Required | Description | Default | | :--------- | :------- | :------------------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------- | | `--schema` | No | Specifies the path to the desired schema.prisma file to be processed instead of the default path. Both absolute and relative paths are supported. | `./schema.prisma`
`./prisma/schema.prisma` | #### Examples #### Start Studio on the default port and open a new browser tab to it ```terminal prisma studio ``` #### Start Studio on a different port and open a new browser tab to it ```terminal prisma studio --port 7777 ``` #### Start Studio and open a Firefox tab to it ```terminal prisma studio --browser firefox ``` #### Start Studio without opening a new browser tab to it ```terminal prisma studio --browser none ``` ## `package.json` entry options ### `schema` The path to the desired `schema.prisma` file can be specified with the `prisma.schema` entry in the `package.json` file. The path defines the file the Prisma CLI should use when you run any of the CLI commands. Both absolute and relative paths are supported. ```json file="package.json" { "name": "my-project", "version": "1.0.0", "prisma": { "schema": "./custom-path-to-schema/schema.prisma" } } ``` This is available from version 2.7.0 and later. ### `seed` The command used to populate the datasource is specified in the `prisma.seed` entry in the `package.json` file. It is used when `prisma db seed` is invoked or triggered. See [Seeding your database](/orm/prisma-migrate/workflows/seeding) ```json file="package.json" { "name": "my-project", "version": "1.0.0", "prisma": { "seed": "node ./prisma/seed.js" } } ``` This is available from version 3.0.1 and later. ## Using a HTTP proxy for the CLI Prisma CLI supports [custom HTTP proxies](https://github.com/prisma/prisma/issues/506). This is particularly relevant when being behind a corporate firewall. To activate usage of the proxy, provide either of the following environment variables: - [`HTTP_PROXY`](/orm/reference/environment-variables-reference#http_proxy) or `http_proxy`: Proxy URL for http traffic, for example `http://localhost:8080` - [`HTTPS_PROXY`](/orm/reference/environment-variables-reference#https_proxy) or `https_proxy`: Proxy URL for https traffic, for example `https://localhost:8080` --- # Error message reference URL: https://www.prisma.io/docs/orm/reference/error-reference For more information about how to work with exceptions and error codes, see [Handling exceptions and errors](/orm/prisma-client/debugging-and-troubleshooting/handling-exceptions-and-errors). ## Prisma Client error types Prisma Client throws different kinds of errors. The following lists the exception types, and their documented data fields: ### `PrismaClientKnownRequestError` Prisma Client throws a `PrismaClientKnownRequestError` exception if the query engine returns a known error related to the request - for example, a unique constraint violation. | **Property** | **Description** | | :-------------- | :--------------------------------------------------------------------------------------------------------------- | | `code` | A Prisma-specific [error code](#error-codes). | | `meta` | Additional information about the error - for example, the field that caused the error: `{ target: [ 'email' ] }` | | `message` | Error message associated with [error code](#error-codes). | | `clientVersion` | Version of Prisma Client (for example, `2.19.0`) | ### `PrismaClientUnknownRequestError` Prisma Client throws a `PrismaClientUnknownRequestError` exception if the query engine returns an error related to a request that does not have an error code. | **Property** | **Description** | | :-------------- | :-------------------------------------------------------- | | `message` | Error message associated with [error code](#error-codes). | | `clientVersion` | Version of Prisma Client (for example, `2.19.0`) | ### `PrismaClientRustPanicError` Prisma Client throws a `PrismaClientRustPanicError` exception if the underlying engine crashes and exits with a non-zero exit code. In this case, Prisma Client or the whole Node process must be restarted. | **Property** | **Description** | | :-------------- | :-------------------------------------------------------- | | `message` | Error message associated with [error code](#error-codes). | | `clientVersion` | Version of Prisma Client (for example, `2.19.0`) | ### `PrismaClientInitializationError` Prisma Client throws a `PrismaClientInitializationError` exception if something goes wrong when the query engine is started and the connection to the database is created. This happens either: - When `prisma.$connect()` is called OR - When the first query is executed Errors that can occur include: - The provided credentials for the database are invalid - There is no database server running under the provided hostname and port - The port that the query engine HTTP server wants to bind to is already taken - A missing or inaccessible environment variable - The query engine binary for the current platform could not be found (`generator` block) | **Property** | **Description** | | :-------------- | :-------------------------------------------------------- | | `errorCode` | A Prisma-specific error code. | | `message` | Error message associated with [error code](#error-codes). | | `clientVersion` | Version of Prisma Client (for example, `2.19.0`) | ### `PrismaClientValidationError` Prisma Client throws a `PrismaClientValidationError` exception if validation fails - for example: - Missing field - for example, an empty `data: {}` property when creating a new record - Incorrect field type provided (for example, setting a `Boolean` field to `"Hello, I like cheese and gold!"`) | **Property** | **Description** | | :-------------- | :----------------------------------------------- | | `message` | Error message. | | `clientVersion` | Version of Prisma Client (for example, `2.19.0`) | ## Error codes ### Common #### `P1000` "Authentication failed against database server at `{database_host}`, the provided database credentials for `{database_user}` are not valid. Please make sure to provide valid database credentials for the database server at `{database_host}`." #### `P1001` "Can't reach database server at `{database_host}`:`{database_port}` Please make sure your database server is running at `{database_host}`:`{database_port}`." #### `P1002` "The database server at `{database_host}`:`{database_port}` was reached but timed out. Please try again. Please make sure your database server is running at `{database_host}`:`{database_port}`. " #### `P1003` "Database \{database_file_name} does not exist at \{database_file_path}" "Database `{database_name}.{database_schema_name}` does not exist on the database server at `{database_host}:{database_port}`." "Database `{database_name}` does not exist on the database server at `{database_host}:{database_port}`." #### `P1008` "Operations timed out after `{time}`" #### `P1009` "Database `{database_name}` already exists on the database server at `{database_host}:{database_port}`" #### `P1010` "User `{database_user}` was denied access on the database `{database_name}`" #### `P1011` "Error opening a TLS connection: \{message}" #### `P1012` **Note:** If you get error code P1012 after you upgrade Prisma ORM to version 4.0.0 or later, see the [version 4.0.0 upgrade guide](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-4#upgrade-your-prisma-schema). A schema that was valid before version 4.0.0 might be invalid in version 4.0.0 and later. The upgrade guide explains how to update your schema to make it valid. "\{full_error}" Possible P1012 error messages: - "Argument `{}` is missing." - "Function `{}` takes {} arguments, but received {}." - "Argument `{}` is missing in attribute `@{}`." - "Argument `{}` is missing in data source block `{}`." - "Argument `{}` is missing in generator block `{}`." - "Error parsing attribute `@{}`: {}" - "Attribute `@{}` is defined twice." - "The model with database name `{}` could not be defined because another model with this name exists: `{}`" - "`{}` is a reserved scalar type name and can not be used." - "The {} `{}` cannot be defined because a {} with that name already exists." - "Key `{}` is already defined in {}." - "Argument `{}` is already specified as unnamed argument." - "Argument `{}` is already specified." - "No such argument."" - "Field `{}` is already defined on model `{}`." - "Field `{}` in model `{}` can't be a list. The current connector does not support lists of primitive types." - "The index name `{}` is declared multiple times. With the current connector index names have to be globally unique." - "Value `{}` is already defined on enum `{}`." - "Attribute not known: `@{}`." - "Function not known: `{}`." - "Datasource provider not known: `{}`." - "shadowDatabaseUrl is the same as url for datasource `{}`. Please specify a different database as shadow database." - "The preview feature `{}` is not known. Expected one of: {}" - "`{}` is not a valid value for {}." - "Type `{}` is neither a built-in type, nor refers to another model, custom type, or enum." - "Type `{}` is not a built-in type." - "Unexpected token. Expected one of: {}" - "Environment variable not found: {}." - "Expected a {} value, but received {} value `{}`." - "Expected a {} value, but failed while parsing `{}`: {}." - "Error validating model `{}`: {}" - "Error validating field `{}` in model `{}`: {}" - "Error validating datasource `{datasource}`: \{message}" - "Error validating enum `{}`: {}" - "Error validating: {}" #### `P1013` "The provided database string is invalid. \{details}" #### `P1014` "The underlying \{kind} for model `{model}` does not exist." #### `P1015` "Your Prisma schema is using features that are not supported for the version of the database.
Database version: \{database_version}
Errors:
\{errors}" #### `P1016` "Your raw query had an incorrect number of parameters. Expected: `{expected}`, actual: `{actual}`." #### `P1017` "Server has closed the connection." ### Prisma Client (Query Engine) #### `P2000` "The provided value for the column is too long for the column's type. Column: \{column_name}" #### `P2001` "The record searched for in the where condition (`{model_name}.{argument_name} = {argument_value}`) does not exist" #### `P2002` "Unique constraint failed on the \{constraint}" #### `P2003` "Foreign key constraint failed on the field: `{field_name}`" #### `P2004` "A constraint failed on the database: `{database_error}`" #### `P2005` "The value `{field_value}` stored in the database for the field `{field_name}` is invalid for the field's type" #### `P2006` "The provided value `{field_value}` for `{model_name}` field `{field_name}` is not valid" #### `P2007` "Data validation error `{database_error}`" #### `P2008` "Failed to parse the query `{query_parsing_error}` at `{query_position}`" #### `P2009` "Failed to validate the query: `{query_validation_error}` at `{query_position}`" #### `P2010` "Raw query failed. Code: `{code}`. Message: `{message}`" #### `P2011` "Null constraint violation on the \{constraint}" #### `P2012` "Missing a required value at `{path}`" #### `P2013` "Missing the required argument `{argument_name}` for field `{field_name}` on `{object_name}`." #### `P2014` "The change you are trying to make would violate the required relation '\{relation_name}' between the `{model_a_name}` and `{model_b_name}` models." #### `P2015` "A related record could not be found. \{details}" #### `P2016` "Query interpretation error. \{details}" #### `P2017` "The records for relation `{relation_name}` between the `{parent_name}` and `{child_name}` models are not connected." #### `P2018` "The required connected records were not found. \{details}" #### `P2019` "Input error. \{details}" #### `P2020` "Value out of range for the type. \{details}" #### `P2021` "The table `{table}` does not exist in the current database." #### `P2022` "The column `{column}` does not exist in the current database." #### `P2023` "Inconsistent column data: \{message}" #### `P2024` "Timed out fetching a new connection from the connection pool. (More info: [http://pris.ly/d/connection-pool](http://pris.ly/d/connection-pool) (Current connection pool timeout: \{timeout}, connection limit: \{connection_limit})" #### `P2025` "An operation failed because it depends on one or more records that were required but not found. \{cause}" #### `P2026` "The current database provider doesn't support a feature that the query used: \{feature}" #### `P2027` "Multiple errors occurred on the database during query execution: \{errors}" #### `P2028` "Transaction API error: \{error}" #### `P2029` "Query parameter limit exceeded error: \{message}" #### `P2030` "Cannot find a fulltext index to use for the search, try adding a @@fulltext([Fields...]) to your schema" #### `P2031` "Prisma needs to perform transactions, which requires your MongoDB server to be run as a replica set. See details: [https://pris.ly/d/mongodb-replica-set](https://pris.ly/d/mongodb-replica-set)" #### `P2033` "A number used in the query does not fit into a 64 bit signed integer. Consider using `BigInt` as field type if you're trying to store large integers" #### `P2034` "Transaction failed due to a write conflict or a deadlock. Please retry your transaction" #### `P2035` "Assertion violation on the database: \{database_error}" #### `P2036` "Error in external connector (id \{id})" #### `P2037` "Too many database connections opened: \{message}" ### Prisma Migrate (Schema Engine) The Schema Engine was previously called Migration Engine. This change was introduced in version [5.0.0](https://github.com/prisma/prisma/releases/tag/5.0.0). #### `P3000` "Failed to create database: \{database_error}" #### `P3001` "Migration possible with destructive changes and possible data loss: \{migration_engine_destructive_details}" #### `P3002` "The attempted migration was rolled back: \{database_error}" #### `P3003` "The format of migrations changed, the saved migrations are no longer valid. To solve this problem, please follow the steps at: [https://pris.ly/d/migrate](https://pris.ly/d/migrate)" #### `P3004` "The `{database_name}` database is a system database, it should not be altered with prisma migrate. Please connect to another database." #### `P3005` "The database schema is not empty. Read more about how to baseline an existing production database: [https://pris.ly/d/migrate-baseline](https://pris.ly/d/migrate-baseline)" #### `P3006` "Migration `{migration_name}` failed to apply cleanly to the shadow database.
\{error_code}Error:
\{inner_error}" #### `P3007` "Some of the requested preview features are not yet allowed in schema engine. Please remove them from your data model before using migrations. (blocked: \{list_of_blocked_features})" #### `P3008` "The migration `{migration_name}` is already recorded as applied in the database." #### `P3009` "migrate found failed migrations in the target database, new migrations will not be applied. Read more about how to resolve migration issues in a production database: [https://pris.ly/d/migrate-resolve](https://pris.ly/d/migrate-resolve)
\{details}" #### `P3010` "The name of the migration is too long. It must not be longer than 200 characters (bytes)." #### `P3011` "Migration `{migration_name}` cannot be rolled back because it was never applied to the database. Hint: did you pass in the whole migration name? (example: \"20201207184859_initial_migration\")" #### `P3012` "Migration `{migration_name}` cannot be rolled back because it is not in a failed state." #### `P3013` "Datasource provider arrays are no longer supported in migrate. Please change your datasource to use a single provider. Read more at [https://pris.ly/multi-provider-deprecation](https://pris.ly/multi-provider-deprecation)" #### `P3014` "Prisma Migrate could not create the shadow database. Please make sure the database user has permission to create databases. Read more about the shadow database (and workarounds) at [https://pris.ly/d/migrate-shadow](https://pris.ly/d/migrate-shadow). Original error: \{error_code}
\{inner_error}" #### `P3015` "Could not find the migration file at \{migration_file_path}. Please delete the directory or restore the migration file." #### `P3016` "The fallback method for database resets failed, meaning Migrate could not clean up the database entirely. Original error: \{error_code}
\{inner_error}" #### `P3017` "The migration \{migration_name} could not be found. Please make sure that the migration exists, and that you included the whole name of the directory. (example: \"20201207184859_initial_migration\")" #### `P3018` "A migration failed to apply. New migrations cannot be applied before the error is recovered from. Read more about how to resolve migration issues in a production database: https://pris.ly/d/migrate-resolve

Migration name: \{migration_name}

Database error code: \{database_error_code}

Database error:
\{database_error} " #### `P3019` "The datasource provider `{provider}` specified in your schema does not match the one specified in the migration_lock.toml, `{expected_provider}`. Please remove your current migration directory and start a new migration history with prisma migrate dev. Read more: [https://pris.ly/d/migrate-provider-switch](https://pris.ly/d/migrate-provider-switch)" #### `P3020` "The automatic creation of shadow databases is disabled on Azure SQL. Please set up a shadow database using the `shadowDatabaseUrl` datasource attribute.
Read the docs page for more details: [https://pris.ly/d/migrate-shadow](https://pris.ly/d/migrate-shadow)" #### `P3021` "Foreign keys cannot be created on this database. Learn more how to handle this: [https://pris.ly/d/migrate-no-foreign-keys](https://pris.ly/d/migrate-no-foreign-keys)" #### `P3022` "Direct execution of DDL (Data Definition Language) SQL statements is disabled on this database. Please read more here about how to handle this: [https://pris.ly/d/migrate-no-direct-ddl](https://pris.ly/d/migrate-no-direct-ddl)" ### `prisma db pull` #### `P4000` "Introspection operation failed to produce a schema file: \{introspection_error}" #### `P4001` "The introspected database was empty." #### `P4002` "The schema of the introspected database was inconsistent: \{explanation}" {/* Error codes generated by https://github.com/mhwelander/doc-tools/blob/master/error_code_parser.py */} ### Prisma Accelerate Prisma Accelerate-related errors start with `P6xxx` except for [`P5011`](/orm/reference/error-reference#p5011-too-many-requests). #### `P6000` (`ServerError`) Generic error to catch all other errors. #### `P6001` (`InvalidDataSource`) The URL is malformed; for instance, it does not use the `prisma://` protocol. #### `P6002` (`Unauthorized`) The API Key in the connection string is invalid. #### `P6003` (`PlanLimitReached`) The included usage of the current plan has been exceeded. This can only occur on the [free plan](https://www.prisma.io/pricing). #### `P6004` (`QueryTimeout`) The global timeout of Accelerate has been exceeded. You can find the limit [here](/accelerate/connection-pooling#query-timeout-limit). > Also see the [troubleshooting guide](/accelerate/troubleshoot#p6004-querytimeout) for more information. #### `P6005` (`InvalidParameters`) The user supplied invalid parameters. Currently only relevant for transaction methods. For example, setting a timeout that is too high. You can find the limit [here](/accelerate/connection-pooling#interactive-transactions-query-timeout-limit). #### `P6006` (`VersionNotSupported`) The chosen Prisma version is not compatible with Accelerate. This may occur when a user uses an unstable development version that we occasionally prune. #### `P6008` (`ConnectionError|EngineStartError`) The engine failed to start. For example, it couldn't establish a connection to the database. > Also see the [troubleshooting guide](/accelerate/troubleshoot#p6008-connectionerrorenginestarterror) for more information. #### `P6009` (`ResponseSizeLimitExceeded`) The global response size limit of Accelerate has been exceeded. You can find the limit [here](/accelerate/connection-pooling#response-size-limit). > Also see the [troubleshooting guide](/accelerate/troubleshoot#p6009-responsesizelimitexceeded) for more information. #### `P6010` (`ProjectDisabledError`) Your accelerate project is disabled. Please [enable](/accelerate/getting-started#1-enable-accelerate) it again to use it. #### `P5011` (`Too Many Requests`) This error indicates that the request volume exceeded. Implement a back-off strategy and try again later. For assistance with expected high workloads, contact [support](/platform/support). --- # Environment variables reference URL: https://www.prisma.io/docs/orm/reference/environment-variables-reference This document describes different environment variables and their use cases. ## Prisma Client ### `DEBUG` `DEBUG` is used to enable debugging output in Prisma Client. Example setting Prisma Client level debugging output: ```terminal # enable only `prisma:client`-level debugging output export DEBUG="prisma:client" ``` See [Debugging](/orm/prisma-client/debugging-and-troubleshooting/debugging) for more information. ### `NO_COLOR` `NO_COLOR` if [truthy](https://developer.mozilla.org/en-US/docs/Glossary/Truthy) will activate the `colorless` setting for error formatting and strip colors from error messages. See [Formatting via environment variables](/orm/prisma-client/setup-and-configuration/error-formatting#formatting-via-environment-variables) for more information. ## Prisma Studio ### `BROWSER` `BROWSER` is for Prisma Studio to force which browser it should be open in, if not set it will open in the default browser. ```terminal BROWSER=firefox prisma studio --port 5555 ``` Alternatively you can set this when starting Studio from the CLI as well: ```terminal prisma studio --browser firefox ``` See [Studio](/orm/reference/prisma-cli-reference#studio) documentation for more information. ## Prisma CLI ### `PRISMA_HIDE_PREVIEW_FLAG_WARNINGS` `PRISMA_HIDE_PREVIEW_FLAG_WARNINGS` hides the warning message that states that a preview feature flag can be removed. It is a truthy value. ### `PRISMA_HIDE_UPDATE_MESSAGE` `PRISMA_HIDE_UPDATE_MESSAGE` is used to hide the update notification message that is shown when a newer Prisma CLI version is available. It's a truthy value. ### `PRISMA_GENERATE_SKIP_AUTOINSTALL` `PRISMA_GENERATE_SKIP_AUTOINSTALL` can be set to a truthy value to skip the auto-install of `prisma` CLI and `@prisma/client` dependencies (if they are missing), if the `prisma-client-js` generator is defined in the Prisma Schema, when using the `prisma generate` command. ### `PRISMA_SKIP_POSTINSTALL_GENERATE` `PRISMA_SKIP_POSTINSTALL_GENERATE` can be set to a truthy value to skip the auto-generation of Prisma Client when its `postinstall` hook is triggered by a package manager. The `postinstall` hook of the `@prisma/client` package is triggered when the package is installed, or its version is updated. ### `PRISMA_DISABLE_WARNINGS` Disables all CLI warnings generated by `logger.warn`. ### `PRISMA_GENERATE_NO_ENGINE` This environment variable is available since version `5.2.0` `PRISMA_GENERATE_NO_ENGINE` can be set to a truthy value to generate a Prisma Client without an included [query engine](/orm/more/under-the-hood/engines) in order to reduce deployed application size when paired with [Prisma Accelerate](/accelerate). ### `PRISMA_SCHEMA_DISABLE_ADVISORY_LOCK` This environment variable is available since version `5.3.0` `PRISMA_SCHEMA_DISABLE_ADVISORY_LOCK` can be set to a truthy value to disable the [advisory locking](/orm/prisma-migrate/workflows/development-and-production#advisory-locking) used by Prisma Migrate. This might be needed, depending on the database configuration, for example, for a Percona-XtraDB-Cluster or MariaDB Galera Cluster. ## Proxy environment variables The Prisma CLI supports custom HTTP(S) proxies to download the Prisma engines. These can be helpful to use when working behind a corporate firewall. See [Using a HTTP proxy for the CLI](/orm/reference/prisma-cli-reference#using-a-http-proxy-for-the-cli) for more information. ### `NO_PROXY` `NO_PROXY` is a comma-separated list of hostnames or IP addresses that do not require a proxy. ```env NO_PROXY=myhostname.com,10.11.12.0/16,172.30.0.0/16 ``` ### `HTTP_PROXY` `HTTP_PROXY` is set with the hostname or IP address of a proxy server. ```env HTTP_PROXY=http://proxy.example.com ``` ### `HTTPS_PROXY` `HTTPS_PROXY` is set with the hostname or IP address of a proxy server. ```env HTTPS_PROXY=https://proxy.example.com ``` ## Engine environment variables ### Configuring Query Engine Type #### `PRISMA_CLI_QUERY_ENGINE_TYPE` `PRISMA_CLI_QUERY_ENGINE_TYPE` is used to [define the query engine type Prisma CLI downloads and uses](/orm/more/under-the-hood/engines#configuring-the-query-engine). Defaults to `library`, but can be set to `binary`: ```env PRISMA_CLI_QUERY_ENGINE_TYPE=binary ``` #### `PRISMA_CLIENT_ENGINE_TYPE` `PRISMA_CLIENT_ENGINE_TYPE` is used to [define the query engine type Prisma Client downloads and uses](/orm/more/under-the-hood/engines#configuring-the-query-engine). Defaults to `library`, but can be set to `binary`: ```env PRISMA_CLIENT_ENGINE_TYPE=binary ``` Note: You need to generate your Prisma Client after setting this variable for the configuration to take effect and the libraries to be downloaded. Otherwise, Prisma Client will be missing the appropriate query engine library and you will _have to_ define their location using [`PRISMA_QUERY_ENGINE_LIBRARY`](#prisma_query_engine_library). It is the environment variable equivalent for the [`engineType` property of the `generator` block](/orm/more/under-the-hood/engines#configuring-the-query-engine) which enables you to define the same setting in your Prisma Schema. ### Downloading Engines #### `PRISMA_ENGINES_MIRROR` `PRISMA_ENGINES_MIRROR` can be used to specify a custom CDN (or server) endpoint to download the engines files for the CLI/Client. The default value is `https://binaries.prisma.sh`, where Prisma hosts the engine files. ```env PRISMA_ENGINES_MIRROR=https://example.org/custom-engines/ ``` See [Prisma engines](/orm/more/under-the-hood/engines#hosting-engines) for a conceptual overview of how to use this environment variable. Note: This environment variable used to be available as `PRISMA_BINARIES_MIRROR`, which was deprecated in Prisma ORM 3.0.1. It is discouraged to use anymore and will be removed in the future. #### `PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING` This environment variable is available since version `4.16.0` `PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING` can be can be set to a truthy value to ignore problems around downloading & verifying the integrity (via a checksum file) of the Prisma ORM engines. This is particularly useful when deploying to an offline system environment where the checksum file cannot be downloaded. ```env PRISMA_ENGINES_CHECKSUM_IGNORE_MISSING=1 ``` Note: we might change the overall download behavior in a future release in a way that this environment variable will not be needed anymore in a offline environment case. ### Custom engine file locations By default, all engine files are downloaded when you install Prisma CLI, copied when generating Prisma Client, and put into known locations. There are however situations where you may want to use a custom engine file from custom locations: #### `PRISMA_QUERY_ENGINE_BINARY` `PRISMA_QUERY_ENGINE_BINARY` is used to set a custom location for your own query engine binary. ```env PRISMA_QUERY_ENGINE_BINARY=custom/query-engine- # Example: ./prisma/binaries/query-engine-linux-arm64-openssl-1.0.x ``` For Prisma CLI it allows you to define the query engine file to be used. For Prisma Client, on build time (during `prisma generate`), it defines where the query engine file will be copied from into Prisma Client. At run time (when using the generated Client) it can be used to define the specific query engine file to be used instead of the included one. Note: This can only have an effect if the engine type of CLI or Client are set to `binary`. If the engine type is `library` (the default), use PRISMA_QUERY_ENGINE_LIBARY instead. #### `PRISMA_QUERY_ENGINE_LIBRARY` `PRISMA_QUERY_ENGINE_LIBRARY` is used to set a custom location for your own query engine library. ```env PRISMA_QUERY_ENGINE_LIBRARY=custom/libquery_engine-.so.node # Example: ./prisma/binaries/libquery_engine-linux-arm64-openssl-1.0.x.so.node ``` For Prisma CLI it allows you to define the query engine file to be used. For Prisma Client, on build time (during `prisma generate`), it defines where the query engine file will be copied from into Prisma Client. At run time (when using the generated Client) it can be used to define the specific query engine file to be used instead of the included one. Note: This can only have an effect if the engine type of CLI or Client are set to `library` (the default) #### `PRISMA_SCHEMA_ENGINE_BINARY` `PRISMA_SCHEMA_ENGINE_BINARY` is used to set a custom location for your Schema engine binary. ```env PRISMA_SCHEMA_ENGINE_BINARY=custom/my-schema-engine-unix ``` #### `PRISMA_MIGRATION_ENGINE_BINARY` **Deprecated**: `PRISMA_MIGRATION_ENGINE_BINARY` variable is deprecated in [5.0.0](https://github.com/prisma/prisma/releases/tag/5.0.0) because Migration engine was renamed to Schema Engine. `PRISMA_MIGRATION_ENGINE_BINARY` is used to set a custom location for your own migration engine binary. ```env PRISMA_MIGRATION_ENGINE_BINARY=custom/my-migration-engine-unix ``` #### `PRISMA_INTROSPECTION_ENGINE_BINARY` `PRISMA_INTROSPECTION_ENGINE_BINARY` is used to set a custom location for your own introspection engine binary. ```env PRISMA_INTROSPECTION_ENGINE_BINARY=custom/my-introspection-engine-unix ``` The Introspection Engine is served by the Migration Engine from [4.9.0](https://github.com/prisma/prisma/releases/tag/4.9.0). Therefore, the `PRISMA_INTROSPECTION_ENGINE` environment variable will not be used. #### `PRISMA_FMT_BINARY` This functionality has been removed in Prisma CLI version 4.10.0. It only works in earlier versions. `PRISMA_FMT_BINARY` is used to set a custom location for your own format engine binary. ```env PRISMA_FMT_BINARY=custom/my-custom-format-engine-unix ``` The `PRISMA_FMT_BINARY` variable is used in versions [4.2.0](https://github.com/prisma/prisma/releases/tag/4.2.0) or lower. ### CLI Binary Targets #### `PRISMA_CLI_BINARY_TARGETS` `PRISMA_CLI_BINARY_TARGETS` can be used to specify one or more binary targets that Prisma CLI will download during installation (so it must be provided during `npm install` of Prisma CLI and does not affect runtime of Prisma CLI or Prisma Client). Use `PRISMA_CLI_BINARY_TARGETS` if you 1) deploy to a specific platform via an upload of a local project that includes dependencies, and 2) your local environment is different from the target (e.g. AWS Lambda with Node.js 20+ is `rhel-openssl-3.0.x`, and your local environment might be macOS arm64 `darwin-arm64`). Using the `PRISMA_CLI_BINARY_TARGETS` environment variable ensures that the target engine files are also downloaded. ```terminal PRISMA_CLI_BINARY_TARGETS=darwin-arm64,rhel-openssl-3.0.x npm install ``` This is the Prisma CLI equivalent for the [`binaryTargets` property of the `generator` block](/orm/prisma-schema/overview/generators#binary-targets), which enables you to define the same setting for Prisma Client. > **Note**: For Node.js versions earlier than 20, the openssl version was 1.0.x instead of 3.0.x. This is most obvious in AWS Lambda deployments, where the binary target would be `rhel-openssl-1.0.x` instead of `rhel-openssl-3.0.x`. --- # Prisma Config reference URL: https://www.prisma.io/docs/orm/reference/prisma-config-reference ## Overview :::warning This feature is currently in [Early Access](/orm/more/releases#early-access) and still subject to change. ::: The `prisma.config.ts` file configures the Prisma CLI, including subcommands like `migrate` and `studio`, using TypeScript. You can define your config in two ways: Using the `defineConfig` helper: ```ts import path from 'node:path'; import { defineConfig } from 'prisma/config'; export default defineConfig({ earlyAccess: true, schema: path.join('prisma', 'schema.prisma'), }); ``` Or using TypeScript's `satisfies` operator with the `PrismaConfig` type: ```ts import path from 'node:path'; import type { PrismaConfig } from 'prisma' export default { earlyAccess: true, schema: path.join('prisma', 'schema.prisma'), } satisfies PrismaConfig ``` ## Configuration interface ```ts export declare type PrismaConfig = { /** * Whether features with an unstable API are enabled. */ earlyAccess: true; /** * The path to the schema file or path to a folder that shall be recursively searched for .prisma files. */ schema?: string; /** * The configuration for Prisma Studio. */ studio?: PrismaStudioConfigShape; /** * The configuration for Prisma Migrate + Introspect */ migrate?: PrismaMigrateConfigShape; }; ``` ## Options reference ### `earlyAccess` - Type: `boolean` - Required: Yes (during Early Access) - Default: none Controls whether the config file is enabled. Must be set to `true` during Early Access. ### `migrate` - Type: `object` - Required: No - Default: `{}` Configures how Prisma Migrate communicates with your underlying database. See sub-options below for details. #### `migrate.adapter` - Type: `(env: Env) => Promise` - Required: No - Default: none A function that returns a Prisma driver adapter instance which is used by the Prisma CLI to run migrations. The function receives an `env` parameter containing environment variables and should return a `Promise` that resolves to a valid Prisma driver adapter. Example using the Prisma ORM D1 driver adapter: ```ts import path from 'node:path' import type { PrismaConfig } from 'prisma' import { PrismaD1HTTP } from '@prisma/adapter-d1' // import your .env file import 'dotenv/config' type Env = { CLOUDFLARE_D1_TOKEN: string CLOUDFLARE_ACCOUNT_ID: string CLOUDFLARE_DATABASE_ID: string } export default { earlyAccess: true, schema: path.join('prisma', 'schema.prisma'), migrate: { async adapter(env) { return new PrismaD1HTTP({ CLOUDFLARE_D1_TOKEN: env.CLOUDFLARE_D1_TOKEN, CLOUDFLARE_ACCOUNT_ID: env.CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_DATABASE_ID: env.CLOUDFLARE_DATABASE_ID, }) }, }, } satisfies PrismaConfig ``` ### `schema` - Type: `string` - Required: No - Default: `./prisma/schema.prisma` and `./schema.prisma` Configures how Prisma ORM locates and loads your schema file(s). Can be a file or folder path. Relative paths are resolved relative to the `prisma.config.ts` file location. See [here](/orm/prisma-schema/overview/location#multi-file-prisma-schema-preview) for more info about schema location options. ### `studio` - Type: `object` - Required: No - Default: none Configures how Prisma Studio connects to your database. #### `studio.adapter` - Type: `(env: Env) => Promise` - Required: No - Default: none A function that returns a Prisma driver adapter instance. The function receives an `env` parameter containing environment variables and should return a `Promise` that resolves to a valid Prisma driver adapter. Example using the Prisma ORM LibSQL driver adapter: ```ts import type { PrismaConfig } from 'prisma' export default { earlyAccess: true, studio: { adapter: async (env: Env) => { const { PrismaLibSQL } = await import('@prisma/adapter-libsql') const { createClient } = await import('@libsql/client') const libsql = createClient({ url: env.DOTENV_PRISMA_STUDIO_LIBSQL_DATABASE_URL, }) return new PrismaLibSQL(libsql) }, }, } satisfies PrismaConfig ``` ## Common patterns ### Setting up your project To get started with Prisma Config, create a `prisma.config.ts` file in your project root. You can use either of these approaches: Using `defineConfig`: ```ts import { defineConfig } from 'prisma/config' export default defineConfig({ earlyAccess: true }) ``` Using TypeScript types: ```ts import type { PrismaConfig } from 'prisma' export default { earlyAccess: true } satisfies PrismaConfig ``` ### Using environment variables When using `prisma.config.ts`, environment variables from `.env` files are not automatically loaded. You'll need to: 1. Install the `dotenv` package: ```terminal npm install dotenv ``` 2. Import `dotenv/config` in your config file: ```ts import 'dotenv/config' import type { PrismaConfig } from 'prisma' export default { earlyAccess: true, // now you can use process.env variables } satisfies PrismaConfig ``` ### Using multi-file schemas If you want to split your Prisma schema into multiple files, you need to use the `prismaSchemaFolder` [Preview feature](/orm/reference/preview-features/client-preview-features) and specify the path to your Prisma schema folder via the `schema` property: ```ts import path from 'node:path'; import type { PrismaConfig } from 'prisma' export default { earlyAccess: true, schema: path.join('prisma', 'schema'), } satisfies PrismaConfig ``` In that case, your `migrations` directory must be located next to the `.prisma` file that defines the `datasource` block. For example, assuming `schema.prisma` defines the `datasource`, here's how how need to place the migrations folder: ``` # `migrations` and `schema.prisma` are on the same level . ├── migrations ├── models │ ├── posts.prisma │ └── users.prisma └── schema.prisma ``` ### Custom config location You can specify a custom location for your config file when running Prisma CLI commands: ```terminal prisma validate --config ./path/to/myconfig.ts ``` --- # Database features matrix URL: https://www.prisma.io/docs/orm/reference/database-features This page gives an overview of the features which are provided by the databases that Prisma ORM supports. Additionally, it explains how each of these features can be used in Prisma ORM with pointers to further documentation. ## Relational database features This section describes which database features exist on the relational databases that are currently supported by Prisma ORM. The **Prisma schema** column indicates how a certain feature can be represented in the [Prisma schema](/orm/prisma-schema) and links to its documentation. Note that database features can be used in **Prisma Client** even though they might not yet be representable in the Prisma schema. :::note These features are _only_ for relational databases. Supported features for NoSQL databases, like MongoDB, can [be found below](#nosql-database-features). ::: ### Constraints | Constraint | Supported | Prisma schema | Prisma Client | Prisma Migrate | | ------------- | :-------: | :--------------------------------------------------------------------------------------: | :-----------: | :------------: | | `PRIMARY KEY` | ✔️ | [`@id` and `@@id`](/orm/prisma-schema/data-model/models#defining-an-id-field) | ✔️ | ✔️ | | `FOREIGN KEY` | ✔️ | [Relation fields](/orm/prisma-schema/data-model/relations#relation-fields) | ✔️ | ✔️ | | `UNIQUE` | ✔️\* | [`@unique` and `@@unique`](/orm/prisma-schema/data-model/models#defining-a-unique-field) | ✔️ | ✔️ | | `CHECK` | ✔️† | Not yet | ✔️ | Not yet | | `NOT NULL` | ✔️ | [`?`](/orm/prisma-schema/data-model/models#type-modifiers) | ✔️ | ✔️ | | `DEFAULT` | ✔️ | [`@default`](/orm/prisma-schema/data-model/models#defining-a-default-value) | ✔️ | ✔️ | > \* [Caveats apply when using the `UNIQUE` constraint with Microsoft SQL Server](/orm/overview/databases/sql-server#data-model-limitations) > † Only supported in MySQL in [version 8 and higher](https://dev.mysql.com/doc/refman/8.0/en/create-table-check-constraints.html). ### Referential Actions (Delete and Update behaviors for foreign key references) | Deletion behavior | Supported | Prisma schema | Prisma Client | Prisma Migrate | | ----------------- | :-------: | :-----------: | :-----------: | :------------: | | `CASCADE` | ✔️ | ✔️ | ✔️ | ✔️ | | `RESTRICT` | ✔️\* | ✔️ | ✔️ | ✔️ | | `NO ACTION` | ✔️ | ✔️ | ✔️ | ✔️ | | `SET DEFAULT` | ✔️ | ✔️ | ✔️ | ✔️ | | `SET NULL` | ✔️ | ✔️ | ✔️ | ✔️ | > \* `RESTRICT` is not supported in Microsoft SQL Server. ### Indexes | Index | Supported | Prisma schema | Prisma Client | Prisma Migrate | | -------------- | :-------------: | :---------------------------------------------------------------------------------------------------------: | :-----------: | :------------: | | `UNIQUE` | ✔️ | [`@unique` and `@@unique`](/orm/prisma-schema/data-model/models#defining-a-unique-field) | ✔️ | ✔️ | | `USING` | PostgreSQL only | [`type`](/orm/prisma-schema/data-model/indexes#configuring-the-access-type-of-indexes-with-type-postgresql) | ✔️ | ✔️ | | `WHERE` | ✔️ | Not yet | ✔️ | Not yet | | `(expression)` | ✔️ | Not yet | ✔️ | Not yet | | `INCLUDE` | PostgreSQL and Microsoft SQL Server only | Not yet | ✔️ | Not yet | Algorithm specified via `USING`: | Index type (Algorithm) | Supported | Prisma schema | Prisma Client | Prisma Migrate | | ---------------------- | :-------: | :-----------: | :-----------: | :------------: | | B-tree | ✔️ | ✔️† | ✔️ | Not yet | | Hash | ✔️ | ✔️† | ✔️ | Not yet | | GiST | ✔️\* | ✔️† | ✔️\* | Not yet | | GIN | ✔️\* | ✔️† | ✔️\* | Not yet | | BRIN | ✔️\* | ✔️† | ✔️\* | Not yet | | SP-GiST | ✔️\* | ✔️† | ✔️\* | Not yet | - \* Not supported for MySQL and SQLite - † Available with the PostgreSQL connector only in Prisma ORM versions `4.0.0` and later. ### Misc | Feature | Supported | Prisma schema | Prisma Client | Prisma Migrate | | --------------------------------- | :-------: | :--------------------------------------------------------------------------------: | :-----------: | :------------: | | Autoincrementing IDs | ✔️ | [`autoincrement()`](/orm/prisma-schema/data-model/models#defining-a-default-value) | ✔️ | ✔️ | | Arrays | PostgreSQL only | [`[]`](/orm/prisma-schema/data-model/models#type-modifiers) | ✔️ | ✔️ | | Enums | ✔️\*† | [`enum`](/orm/prisma-schema/data-model/models#defining-enums) | ✔️ | ✔️ | | Native database types | ✔️ | ✔️ | ✔️ | Not yet | | SQL Views | ✔️ | Not yet | Not yet | Not yet | | JSON support | ✔️† | ✔️ | ✔️ | ✔️ | | Fuzzy/Phrase full text search | ✔️‡ | Not yet | Not yet | Not yet | | Table inheritance | PostgreSQL and Microsoft SQL Server only | Not yet | ✔️ | Not yet | | Authorization and user management | ✔️‡ | Not yet | Not yet | Not yet | - \* Not supported by Microsoft SQL Server - † JSON and Enum types are supported in SQLite as of Prisma ORM 6.2.0. - ‡ Not supported by SQLite ## NoSQL database features This section describes which database features exist on the NoSQL databases that are currently supported by Prisma ORM. ### MongoDB The following table lists common MongoDB features and describes the level of support offered by Prisma ORM: | Feature | Supported by Prisma ORM | Notes | | ----------------------------------------- | :---------------------: | :---------------------------------------------------------------------------------------------: | | Embedded documents | ✔️ | | | Transactions | ✔️ | | | Indexes | ✔️ with caveats | Indexes can only be introspected if the field they refer to includes at least some data. | | Autoincrementing IDs | No | | | Compound IDs | No | MongoDB does not support composite IDs (`@@id`) | | Generated `ObjectId` | ✔️ | See: [Defining IDs for MongoDB](/orm/prisma-schema/data-model/models#defining-ids-in-mongodb) | | Arrays | ✔️ | | | Enums | ✔️ | Implemented at Prisma ORM level | | Native database types | ✔️ | See: [Field mapping reference](/orm/reference/prisma-schema-reference#model-field-scalar-types) | | JSON support | ✔️ | Advanced `Json` field filtering is not yet supported. | | DBrefs | No | | Change streams | No | | Direct access to the aggregation pipeline | No | --- # Supported databases URL: https://www.prisma.io/docs/orm/reference/supported-databases Prisma ORM currently supports the following databases. > See also: [System requirements](/orm/reference/system-requirements). An asterisk (\*) indicates that the version number is not relevant; either all versions are supported, there is not a public version number, etc. ## Self-hosted databases | Database | Version | | -------------------- | ------- | | CockroachDB | 21.2.4+ | | MariaDB | 10.0+ | | MariaDB | 11.0+ | | Microsoft SQL Server | 2017 | | Microsoft SQL Server | 2019 | | Microsoft SQL Server | 2022 | | MongoDB | 4.2+ | | MySQL | 5.6 | | MySQL | 5.7 | | MySQL | 8.0 | | PostgreSQL | 9.6 | | PostgreSQL | 10 | | PostgreSQL | 11 | | PostgreSQL | 12 | | PostgreSQL | 13 | | PostgreSQL | 14 | | PostgreSQL | 15 | | PostgreSQL | 16 | | PostgreSQL | 17 | | SQLite | \* | Note that a fixed version of SQLite is shipped with every Prisma ORM release. ## Managed databases | Database | Version | | ---------------------------- | ------- | | AWS Aurora | \* | | AWS Aurora Serverless ¹ | \* | | Azure SQL | \* | | CockroachDB-as-a-Service | \* | | MongoDB Atlas | \* | | Neon Serverless Postgres | \* | | PlanetScale | \* | | Cloudflare D1 (Preview) | \* | | Aiven (MySQL & Postgres) | \* | ¹ This does not include support for [Data API for Aurora Serverless](https://github.com/prisma/prisma/issues/1964). --- # Connection URLs URL: https://www.prisma.io/docs/orm/reference/connection-urls Prisma ORM needs a connection URL to be able to connect to your database, e.g. when sending queries with [Prisma Client](/orm/prisma-client) or when changing the database schema with [Prisma Migrate](/orm/prisma-migrate). The connection URL is provided via the `url` field of a `datasource` block in your Prisma schema. It usually consists of the following components (except for SQLite and [Prisma Postgres](/postgres)): - **User**: The name of your database user - **Password**: The password for your database user - **Host**: The IP or domain name of the machine where your database server is running - **Port**: The port on which your database server is running - **Database name**: The name of the database you want to use Make sure you have this information at hand when getting started with Prisma ORM. If you don't have a database server running yet, you can either use a local SQLite database file (see the [Quickstart](/getting-started/quickstart-sqlite)) or [setup a free PostgreSQL database with Prisma Postgres](/postgres). ## Format The format of the connection URL depends on the _database connector_ you're using. Prisma ORM generally supports the standard formats for each database. You can find out more about the connection URL of your database on the dedicated docs page: - [PostgreSQL](/orm/overview/databases/postgresql) - [MySQL](/orm/overview/databases/mysql) - [SQLite](/orm/overview/databases/sqlite) - [MongoDB](/orm/overview/databases/mongodb) - [Microsoft SQL Server](/orm/overview/databases/sql-server) - [CockroachDB](/orm/overview/databases/cockroachdb) ### Special characters For MySQL, PostgreSQL and CockroachDB you must [percentage-encode special characters](https://developer.mozilla.org/en-US/docs/Glossary/Percent-encoding) in any part of your connection URL - including passwords. For example, `p@$$w0rd` becomes `p%40%24%24w0rd`. For Microsoft SQL Server, you must [escape special characters](/orm/overview/databases/sql-server#connection-details) in any part of your connection string. ## Examples Here are examples for the connection URLs of the databases Prisma ORM supports: ### Prisma Postgres [Prisma Postgres](/postgres) uses a special connection string format. It doesn't require a user/password like a conventional PostgreSQL database does. Instead, authentication works via an API key: ```prisma file=schema.prisma datasource db { provider = "postgresql" url = "prisma+postgres://accelerate.prisma-data.net/?api_key=API_KEY" } ``` In this snippet, `API_KEY` is a placeholder for the API key you are receiving when setting up a new Prismas Postgres instance via the [Prisma Console](https://console.prisma.io). Here is an example for what a real connection URL to Prisma Postgres may look like: ```prisma file=schema.prisma datasource db { provider = "postgresql" url = "prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcGlfa2V5IjoiMGNkZTFlMjQtNzhiYi00NTY4LTkyM2EtNWUwOTEzZWUyNjU1IiwidGVuYW50X2lkIjoiNzEyZWRlZTc1Y2U2MDk2ZjI4NDg3YjE4NWMyYzA2OTNhNGMxNzJkMjhhOWFlNGUwZTYxNWE4NWIxZWY1YjBkMCIsImludGVybmFsX3NlY3JldCI6IjA4MzQ2Y2RlLWI5ZjktNDQ4Yy04NThmLTMxNjg4ODEzNmEzZCJ9.N1Za6q6NfInzHvRkud6Ojt_-RFg18a0601vdYWGKOrk" } ``` ### PostgreSQL ```prisma file=schema.prisma datasource db { provider = "postgresql" url = "postgresql://janedoe:mypassword@localhost:5432/mydb?schema=sample" } ``` ### MySQL ```prisma file=schema.prisma datasource db { provider = "mysql" url = "mysql://janedoe:mypassword@localhost:3306/mydb" } ``` ### Microsoft SQL Server ```prisma file=schema.prisma datasource db { provider = "sqlserver" url = "sqlserver://localhost:1433;initial catalog=sample;user=sa;password=mypassword;" } ``` ### SQLite ```prisma file=schema.prisma datasource db { provider = "sqlite" url = "file:./dev.db" } ``` ### CockroachDB ```prisma file=schema.prisma datasource db { provider = "cockroachdb" url = "postgresql://janedoe:mypassword@localhost:26257/mydb?schema=public" } ``` ### MongoDB ```prisma file=schema.prisma datasource db { provider = "mongodb" url = "mongodb+srv://root:@cluster0.ab1cd.mongodb.net/myDatabase?retryWrites=true&w=majority" } ``` ## .env You can also provide the connection URL as an environment variable: ```prisma file=schema.prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` You can then either set the environment variable in your terminal or by providing a [dotenv](https://github.com/motdotla/dotenv) file named `.env`. This will automatically be picked up by the Prisma CLI. Prisma ORM reads the connection URL from the dotenv file in the following situations: - When it updates the schema during build time - When it connects to the database during run time ``` DATABASE_URL=postgresql://janedoe:mypassword@localhost:5432/mydb ``` --- # System requirements URL: https://www.prisma.io/docs/orm/reference/system-requirements This page provides an overview of the system requirements for Prisma ORM. ## System requirements This section lists the software that Prisma ORM requires and the supported operating systems, along with runtime dependency requirements for specific operating systems. ### Software requirements The latest version of Prisma ORM requires the following software: | Tool | Minimum required version | | :-------------------- | :----------------------- | | Node.js | 18.8 / 20.9 / 22.11 | | TypeScript (optional) | 5.1.X | | Yarn (optional) | 1.19.2 | - Prisma ORM supports and tests all _Active LTS_ and _Maintenance LTS_ **Node.js** releases. [Releases that are not in these states like _Current_, and also odd-numbered versions](https://nodejs.org/en/about/releases/) probably also work, but are not recommended for production use. - **TypeScript** is only required for TypeScript users. - When using **Yarn 1**, `1.19.2` is the minimum version compatible with Prisma Client. See also: [Supported database versions](/orm/reference/supported-databases)
Expand for earlier versions ### Prisma ORM v5 Prisma ORM v5 requires the following software: | | Minimum required version | | :-------------------- | :----------------------- | | Node.js | 16.13 / 18.X / 20.X | | TypeScript (optional) | 4.7.X | | Yarn (optional) | 1.19.2 |
### Operating systems Prisma ORM is supported on macOS, Windows and most Linux distributions. #### Linux runtime dependencies Prisma ORM requires the following system libraries to be installed to work: - OpenSSL 1.0.x, 1.1.x or 3.x - zlib (`libz.so.1`) - libgcc (`libgcc_s.so.1`) - C standard library (glibc on most Linux distributions or musl libc on Alpine Linux) The following two tables show the supported Linux distro families, OpenSSL versions and C standard libraries for each CPU architecture. On `AMD64` (`x86_64`) architecture: | Distro family | OpenSSL version | libc version | | ---------------- | ----------------- | ------------ | | Alpine | 1.1.x, 3.x | musl 1.2.x | | RHEL | 1.0.x, 1.1.x, 3.x | glibc 2.17+ | | Debian or others | 1.0.x | glibc 2.19+ | | Debian or others | 1.1.x, 3.x | glibc 2.24+ | On `ARM64` (`aarch64`) architecture: | Distro family | OpenSSL version | libc version | | ---------------- | ----------------- | ------------ | | Alpine | 1.1.x, 3.x | musl 1.2.x | | RHEL | 1.0.x, 1.1.x, 3.x | glibc 2.24+ | | Debian or others | 1.0.x, 1.1.x, 3.x | glibc 2.24+ | When Prisma ORM can not resolve the OpenSSL version on a system (e.g. because it is not installed), it will default to OpenSSL 1.1.x. Systems that can run the supported Node.js versions will most likely have zlib and libgcc available. One notable exception is Google's Distroless images, where `libz.so.1` needs to be copied from a compatible Debian system. #### Windows runtime dependencies On Windows [Microsoft Visual C++ Redistributable 2015](https://download.microsoft.com/download/9/3/F/93FCF1E7-E6A4-478B-96E7-D4B285925B00/vc_redist.x64.exe) or newer must be installed (which is by default the case on most modern installations). #### macOS runtime dependencies Prisma ORM supports macOS 10.15 or newer. There are no additional platform-specific requirements on macOS other than what is listed for all platforms in the [Software requirements](#software-requirements) section. ## Troubleshooting There are some common problems caused by using outdated versions of the system requirements: ### Unable to build a TypeScript project with `@prisma/client` #### Problem You see the following error when you try type-checking a project after you run `prisma generate`. ```terminal wrap ./node_modules/.prisma/client/index.d.ts:10:33 Type error: Type expected. 8 | export type PrismaPromise = Promise & {[prisma]: true} 9 | type UnwrapTuple = { > 10 | [K in keyof Tuple]: K extends `${number}` ? Tuple[K] extends PrismaPromise ? X : never : never | ^ 11 | }; 12 | 13 | ``` #### Solution Upgrade the TypeScript dependency in your project to a [version supported by Prisma ORM](#software-requirements). `npm install -D typescript`. ### Unable to use `groupBy` preview feature #### Problem You see the following console error when you attempt to run an app that uses the `groupBy` preview feature: ```terminal wrap server.ts:6:25 - error TS2615: Type of property 'OR' circularly references itself in mapped type '{ [K in keyof { AND?: Enumerable; OR?: Enumerable; ... 4 more ...; category?: string | StringWithAggregatesFilter; }]: Or<...> extends 1 ? { ...; }[K] extends infer TK ? GetHavingFields<...> : never : {} extends FieldPaths<...> ? never : K...'. 6 const grouped = await prisma.product.groupBy({ ~~~~~~~~~~~~~~~~~~~~~~~~ 7 by: ['category'] ~~~~~~~~~~~~~~~~~~~~ 8 }); ~~~~ server.ts:6:48 - error TS2554: Expected 0 arguments, but got 1. 6 const grouped = await prisma.product.groupBy({ ~ 7 by: ['category'] ~~~~~~~~~~~~~~~~~~~~ 8 }); ~~~ ``` #### Solution Upgrade the TypeScript dependency in your project to a [version supported by Prisma ORM](#software-requirements). `npm install -D typescript`. --- # Prisma Client & Prisma schema URL: https://www.prisma.io/docs/orm/reference/preview-features/client-preview-features When we release a new Prisma Client or Prisma schema feature, it often starts in Preview so that you can test it and submit your feedback. After we improve the feature with your feedback and are satisfied with the internal test results, we promote the feature to general availability. For more information, see [ORM releases and maturity levels](/orm/more/releases). ## Currently active Preview features The following [Preview](/orm/more/releases#preview) feature flags are available for Prisma Client and Prisma schema: | Feature | Released into Preview | Feedback issue | | ------------------------------------------------------------------------------------- | :------------------------------------------------------------- | :-------------------------------------------------------------------: | | [`metrics`](/orm/prisma-client/observability-and-logging/metrics) | [3.15.0](https://github.com/prisma/prisma/releases/tag/3.15.0) | [Submit feedback](https://github.com/prisma/prisma/issues/13579) | | [`multiSchema`](https://github.com/prisma/prisma/issues/1122#issuecomment-1231773471) | [4.3.0](https://github.com/prisma/prisma/releases/tag/4.3.0) | [Submit feedback](https://github.com/prisma/prisma/issues/15077) | | [`postgresqlExtensions`](/orm/prisma-schema/postgresql-extensions) | [4.5.0](https://github.com/prisma/prisma/releases/tag/4.5.0) | [Submit feedback](https://github.com/prisma/prisma/issues/15835) | | [`deno`](/orm/prisma-client/deployment/edge/deploy-to-deno-deploy) | [4.5.0](https://github.com/prisma/prisma/releases/tag/4.5.0) | [Submit feedback](https://github.com/prisma/prisma/issues/15844) | | [`views`](/orm/prisma-schema/data-model/views) | [4.9.0](https://github.com/prisma/prisma/releases/tag/4.9.0) | [Submit feedback](https://github.com/prisma/prisma/issues/17335) | | `driverAdapters` | [5.4.0](https://github.com/prisma/prisma/releases/tag/5.4.0) | [Submit feedback](https://github.com/prisma/prisma/issues/3108) | | `relationJoins` | [5.7.0](https://github.com/prisma/prisma/releases/tag/5.7.0) | [Submit feedback](https://github.com/prisma/prisma/discussions/22288) | | `nativeDistinct` | [5.7.0](https://github.com/prisma/prisma/releases/tag/5.7.0) | [Submit feedback](https://github.com/prisma/prisma/discussions/22287) | | [`prismaSchemaFolder`](/orm/prisma-schema/overview/location#multi-file-prisma-schema-preview) | [5.15.0](https://github.com/prisma/prisma/releases/tag/5.15.0) | [Submit feedback](https://github.com/prisma/prisma/discussions/24413) | | `typedSql` | [5.19.0](https://github.com/prisma/prisma/releases/tag/5.19.0) | [Submit feedback](https://github.com/prisma/prisma/discussions/25106) | | `strictUndefinedChecks` | [5.20.0](https://github.com/prisma/prisma/releases/tag/5.20.0) | [Submit feedback](https://github.com/prisma/prisma/discussions/25271) | | [`fullTextSearchPostgres`](/orm/prisma-client/queries/full-text-search) | [6.0.0](https://github.com/prisma/prisma/releases/tag/6.0.0) | [Submit feedback](https://github.com/prisma/prisma/issues/25773) | | [`prisma-client`](/orm/prisma-schema/overview/generators#prisma-client-early-access) | [6.6.0](https://pris.ly/release/6.6.0) | [Submit feedback](https://github.com/prisma/prisma/issues/25773) | To enable a Preview feature, [add the feature flag to the `generator` block](#enabling-a-prisma-client-preview-feature) in your `schema.prisma` file. [Share your feedback on all Preview features on GitHub](https://github.com/prisma/prisma/issues/3108). ## Enabling a Prisma Client Preview feature To enable a Prisma Client Preview feature: 1. Add the Preview feature flag to the `generator` block: ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["relationJoins"] } ``` 2. Re-generate Prisma Client: ```terminal npx prisma generate ``` 3. If you are using Visual Studio Code and the Preview feature is not available in your `.ts` file after generating Prisma Client, run the **TypeScript: Restart TS server** command. ## Preview features promoted to general availability In the list below, you can find a history of Prisma Client and Prisma schema features that were in Preview and are now in general availability. The features are sorted by the most recent version in which they were promoted to general availability. | Feature | Released into Preview | Released into General Availability | | ------------------- | :------------------------------------------------------------- | :--------------------------------- | | `omitApi` | [5.13.0](https://github.com/prisma/prisma/releases/tag/5.13.0) | [6.2.0](https://github.com/prisma/prisma/releases/tag/6.2.0) | | `jsonProtocol` | [4.11.0](https://github.com/prisma/prisma/releases/tag/4.11.0) | [5.0.0](https://github.com/prisma/prisma/releases/tag/5.0.0) | | [`extendedWhereUnique`](/orm/reference/prisma-client-reference#filter-on-non-unique-fields-with-userwhereuniqueinput) | [4.5.0](https://github.com/prisma/prisma/releases/tag/4.5.0) | [5.0.0](https://github.com/prisma/prisma/releases/tag/5.0.0) | | [`fieldReference`](/orm/reference/prisma-client-reference#compare-columns-in-the-same-table) | [4.3.0](https://github.com/prisma/prisma/releases/tag/4.3.0) | [5.0.0](https://github.com/prisma/prisma/releases/tag/5.0.0) | | [`clientExtensions`](/orm/prisma-client/client-extensions) | [4.7.0](https://github.com/prisma/prisma/releases/tag/4.7.0) | [4.16.0](https://github.com/prisma/prisma/releases/tag/4.16.0) | | [`filteredRelationCount`](/orm/prisma-client/queries/aggregation-grouping-summarizing#filter-the-relation-count) | [4.3.0](https://github.com/prisma/prisma/releases/tag/4.3.0) | [4.16.0](https://github.com/prisma/prisma/releases/tag/4.16.0) | | [`tracing`](/orm/prisma-client/observability-and-logging/opentelemetry-tracing) | [4.2.0](https://github.com/prisma/prisma/releases/tag/4.2.0) | [6.1.0](https://github.com/prisma/prisma/releases/tag/6.1.0) | | [`orderByNulls`](/orm/prisma-client/queries/filtering-and-sorting#sort-with-null-records-first-or-last) | [4.1.0](https://github.com/prisma/prisma/releases/tag/4.1.0) | [4.16.0](https://github.com/prisma/prisma/releases/tag/4.16.0) | | [`referentialIntegrity`](/orm/prisma-schema/data-model/relations/relation-mode) | [3.1.1](https://github.com/prisma/prisma/releases/tag/3.1.1) | [4.7.0](https://github.com/prisma/prisma/releases/tag/4.7.0) | | [`interactiveTransactions`](/orm/prisma-client/queries/transactions#interactive-transactions) | [2.29.0](https://github.com/prisma/prisma/releases/tag/2.29.0) |
  • [4.7.0](https://github.com/prisma/prisma/releases/tag/4.7.0)
  • with Prisma Accelerate [5.1.1](https://github.com/prisma/prisma/releases/tag/5.1.1)
| | [`extendedIndexes`](/orm/prisma-schema/data-model/indexes) | [3.5.0](https://github.com/prisma/prisma/releases/tag/3.5.0)| [4.0.0](https://github.com/prisma/prisma/releases/tag/4.0.0) | | [`filterJson`](/orm/prisma-client/special-fields-and-types/working-with-json-fields#filter-on-a-json-field-simple) | [2.23.0](https://github.com/prisma/prisma/releases/tag/2.23.0) | [4.0.0](https://github.com/prisma/prisma/releases/tag/4.0.0) | | [`improvedQueryRaw`](/orm/prisma-client/using-raw-sql/raw-queries#raw-query-type-mapping) | [3.14.0](https://github.com/prisma/prisma/releases/tag/3.14.0) | [4.0.0](https://github.com/prisma/prisma/releases/tag/4.0.0) | | [`cockroachdb`](/orm/overview/databases/cockroachdb) |
  • [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0)
  • migrations in CockroachDB in [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0)
| [3.14.0](https://github.com/prisma/prisma/releases/tag/3.14.0) | | [`mongodb`](/orm/overview/databases/mongodb) |
  • [2.27.0](https://github.com/prisma/prisma/releases/tag/2.27.0)
  • introspection of MongoDB in [3.2.0](https://github.com/prisma/prisma/releases/tag/3.2.0)
  • introspection of embedded documents in [3.4.0](https://github.com/prisma/prisma/releases/tag/3.4.0)
  • MongoDB embedded documents in [3.10.0](https://github.com/prisma/prisma/releases/tag/3.10.0)
  • introspection of embedded documents in [3.10.0](https://github.com/prisma/prisma/releases/tag/3.10.0)
  • raw query support for MongoDB in [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0)
  • filters in embedded documents as an Experimental Feature in [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0)
  • order by embedded documents in [3.11.0](https://github.com/prisma/prisma/releases/tag/3.11.0)
| [3.12.0](https://github.com/prisma/prisma/releases/tag/3.12.0) | | [`microsoftSqlServer`](/orm/overview/databases/sql-server) | [2.10.0](https://github.com/prisma/prisma/releases/tag/2.10.0) | [3.0.1](https://github.com/prisma/prisma/releases/tag/3.0.1) | | [`namedConstraints`](/orm/prisma-schema/data-model/database-mapping#constraint-and-index-names) | [2.29.0](https://github.com/prisma/prisma/releases/tag/2.29.0) | [3.0.1](https://github.com/prisma/prisma/releases/tag/3.0.1) | | [`referentialActions`](/orm/prisma-schema/data-model/relations/referential-actions) | [2.26.0](https://github.com/prisma/prisma/releases/tag/2.26.0) | [3.0.1](https://github.com/prisma/prisma/releases/tag/3.0.1) | | [`orderByAggregateGroup`](/orm/prisma-client/queries/aggregation-grouping-summarizing#order-by-aggregate-group) | [2.21.0](https://github.com/prisma/prisma/releases/tag/2.21.0) | [3.0.1](https://github.com/prisma/prisma/releases/tag/3.0.1) | | [`orderByRelation`](/orm/prisma-client/queries/filtering-and-sorting#sort-by-relation) |
  • [2.16.0](https://github.com/prisma/prisma/releases/tag/2.16.0)
  • order by aggregates of relations in [2.19.0](https://github.com/prisma/prisma/releases/tag/2.19.0)
| [3.0.1](https://github.com/prisma/prisma/releases/tag/3.0.1) | | [`selectRelationCount`](/orm/prisma-client/queries/aggregation-grouping-summarizing#count-relations) | [2.20.0](https://github.com/prisma/prisma/releases/tag/2.20.0) | [3.0.1](https://github.com/prisma/prisma/releases/tag/3.0.1) | | `napi` | [2.20.0](https://github.com/prisma/prisma/releases/tag/2.20.0) | [3.0.1](https://github.com/prisma/prisma/releases/tag/3.0.1) | | [`groupBy`](/orm/reference/prisma-client-reference#groupby) | [2.14.0](https://github.com/prisma/prisma/releases/tag/2.14.0) | [2.20.0](https://github.com/prisma/prisma/releases/tag/2.20.0) | | [`createMany`](/orm/reference/prisma-client-reference#createmany) | [2.16.0](https://github.com/prisma/prisma/releases/tag/2.16.0) | [2.20.0](https://github.com/prisma/prisma/releases/tag/2.20.0) | | [`nativeTypes`](/orm/prisma-schema/data-model/models#native-types-mapping) | [2.11.0](https://github.com/prisma/prisma/releases/tag/2.11.0) | [2.17.0](https://github.com/prisma/prisma/releases/tag/2.17.0) | | [`uncheckedScalarInputs`](/orm/prisma-client/queries/relation-queries#create-a-single-record-and-multiple-related-records) | [2.11.0](https://github.com/prisma/prisma/releases/tag/2.11.0) | [2.15.0](https://github.com/prisma/prisma/releases/tag/2.15.0) | | [`transactionApi`](/orm/prisma-client/queries/transactions#the-transaction-api) | [2.1.0](https://github.com/prisma/prisma/releases/tag/2.1.0) | [2.11.0](https://github.com/prisma/prisma/releases/tag/2.11.0) | | [`connectOrCreate`](/orm/reference/prisma-client-reference#connectorcreate) | [2.1.0](https://github.com/prisma/prisma/releases/tag/2.1.0) | [2.11.0](https://github.com/prisma/prisma/releases/tag/2.11.0) | | [`atomicNumberOperations`](/orm/reference/prisma-client-reference#atomic-number-operations) | [2.6.0](https://github.com/prisma/prisma/releases/tag/2.6.0) | [2.10.0](https://github.com/prisma/prisma/releases/tag/2.10.0) | | [`insensitiveFilters` (PostgreSQL)](/orm/prisma-client/queries/filtering-and-sorting#case-insensitive-filtering) | [2.5.0](https://github.com/prisma/prisma/releases/tag/2.5.0) | [2.8.0](https://github.com/prisma/prisma/releases/tag/2.8.0) | | [`middlewares`](/orm/prisma-client/client-extensions/middleware) | [2.3.0](https://github.com/prisma/prisma/releases/tag/2.3.0) | [2.5.0](https://github.com/prisma/prisma/releases/tag/2.5.0) | | [`aggregateApi`](/orm/prisma-client/queries/aggregation-grouping-summarizing#aggregate) | [2.2.0](https://github.com/prisma/prisma/releases/tag/2.2.0) | [2.5.0](https://github.com/prisma/prisma/releases/tag/2.5.0) | | [`distinct`](/orm/reference/prisma-client-reference#distinct) | [2.3.0](https://github.com/prisma/prisma/releases/tag/2.3.0) | [2.5.0](https://github.com/prisma/prisma/releases/tag/2.5.0) | --- # Prisma CLI Preview features URL: https://www.prisma.io/docs/orm/reference/preview-features/cli-preview-features When we release a new Prisma CLI feature, it often starts in Preview so that you can test it and submit your feedback. After we improve the feature with your feedback and are satisfied with the internal test results, we promote the feature to general availability. For more information, see [ORM releases and maturity levels](/orm/more/releases). ## Currently active Preview features There are currently no [Preview](/orm/more/releases#preview) features for Prisma CLI. ## Preview features promoted to general availability In the list below, you can find a history of Prisma CLI features that were in Preview and are now in general availability. The features are sorted by the most recent version in which they were promoted to general availability. | Features | Released in Preview | Released in general availability | | --------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------- | | [`prisma migrate diff`](/orm/prisma-migrate/workflows/patching-and-hotfixing#fixing-failed-migrations-with-migrate-diff-and-db-execute) | [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0) | [3.13.0](https://github.com/prisma/prisma/releases/tag/3.13.0) | | [`prisma db execute`](/orm/prisma-migrate/workflows/patching-and-hotfixing#fixing-failed-migrations-with-migrate-diff-and-db-execute) | [3.9.0](https://github.com/prisma/prisma/releases/tag/3.9.0) | [3.13.0](https://github.com/prisma/prisma/releases/tag/3.13.0) | | [`prisma db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) | [2.10.0](https://github.com/prisma/prisma/releases/tag/2.10.0) | [2.22.0](https://github.com/prisma/prisma/releases/tag/2.22.0) | | [`prisma migrate`](/orm/prisma-migrate) | [2.13.0](https://github.com/prisma/prisma/releases/tag/2.13.0) | [2.19.0](https://github.com/prisma/prisma/releases/tag/2.19.0) | --- # Preview features URL: https://www.prisma.io/docs/orm/reference/preview-features/index Some Prisma ORM features are released as [Previews](/orm/more/releases#preview). [Share your feedback on all Preview features on GitHub](https://github.com/prisma/prisma/issues/3108). For information about available preview features and how to enable them, see: - [Prisma Client and Prisma schema preview features](/orm/reference/preview-features/client-preview-features) - [Prisma CLI preview features](/orm/reference/preview-features/cli-preview-features) For information regarding upgrading Prisma ORM and enabling Preview features see [Upgrading to use Preview features](/orm/more/upgrade-guides/upgrading-to-use-preview-features). --- # Reference URL: https://www.prisma.io/docs/orm/reference/index The reference section of the documentation is a collection of reference pages that describe the Prisma ORM APIs and database implementations. ## In this section --- # Engines URL: https://www.prisma.io/docs/orm/more/under-the-hood/engines From a technical perspective, Prisma Client consists of three major components: - JavaScript client library - TypeScript type definitions - A query engine All of these components are located in the [generated `.prisma/client` folder](/orm/prisma-client/setup-and-configuration/generating-prisma-client#the-prismaclient-npm-package) after you ran `prisma generate`. This page covers relevant technical details about the query engine. ## Prisma engines At the core of each module, there typically is a [Prisma engine](https://github.com/prisma/prisma-engines) that implements the core set of functionality. Engines are implemented in [Rust](https://www.rust-lang.org/) and expose a low-level API that is used by the higher-level interfaces. A Prisma engine is the **direct interface to the database**, any higher-level interfaces always communicate with the database _through_ the engine-layer. As an example, Prisma Client connects to the [query engine](/orm/more/under-the-hood/engines) in order to read and write data in a database: ![Prisma engine](./typical-flow-query-engine-at-runtime.png) ### Using custom engine libraries or binaries By default, all engine files are automatically downloaded into the `node_modules/@prisma/engines` folder when you install or update `prisma`, the Prisma CLI package. The [query engine](/orm/more/under-the-hood/engines) is also copied to the generated Prisma Client when you call `prisma generate`. You might want to use a [custom library or binary](https://github.com/prisma/prisma-engines) file if: - Automated download of engine files is not possible. - You have created your own engine library or binary for testing purposes, or for an OS that is not officially supported. Use the following environment variables to specify custom locations for your binaries: - [`PRISMA_QUERY_ENGINE_LIBRARY`](/orm/reference/environment-variables-reference#prisma_query_engine_library) (Query engine, library) - [`PRISMA_QUERY_ENGINE_BINARY`](/orm/reference/environment-variables-reference#prisma_query_engine_binary) (Query engine, binary) - [`PRISMA_SCHEMA_ENGINE_BINARY`](/orm/reference/environment-variables-reference#prisma_schema_engine_binary) (Schema engine) - [`PRISMA_MIGRATION_ENGINE_BINARY`](/orm/reference/environment-variables-reference#prisma_migration_engine_binary) (Migration engine) - [`PRISMA_INTROSPECTION_ENGINE_BINARY`](/orm/reference/environment-variables-reference#prisma_introspection_engine_binary) (Introspection engine) - `PRISMA_MIGRATION_ENGINE_BINARY` variable is deprecated in [5.0.0](https://github.com/prisma/prisma/releases/tag/5.0.0). - The Introspection Engine is served by the Migration Engine from [4.9.0](https://github.com/prisma/prisma/releases/tag/4.9.0). Therefore, the `PRISMA_INTROSPECTION_ENGINE` environment variable will not be used. - The `PRISMA_FMT_BINARY` variable is used in versions [4.2.0](https://github.com/prisma/prisma/releases/tag/4.2.0) or lower. #### Setting the environment variable You can define environment variables globally on your machine or in the `.env` file. ##### a) The `.env` file Add the environment variable to the [`.env` file](/orm/more/development-environment/environment-variables). ``` PRISMA_QUERY_ENGINE_BINARY=custom/my-query-engine-unix ``` ``` PRISMA_QUERY_ENGINE_BINARY=c:\custom\path\my-query-engine-binary.exe ``` > **Note**: It is possible to [use an `.env` file in a location outside the `prisma` folder](/orm/more/development-environment/environment-variables). ##### b) Global environment variable Run the following command to set the environment variable globally (in this example, `PRISMA_QUERY_ENGINE_BINARY`): ```terminal export PRISMA_QUERY_ENGINE_BINARY=/custom/my-query-engine-unix ``` ```terminal set PRISMA_QUERY_ENGINE_BINARY=c:\custom\my-query-engine-windows.exe ``` #### Test your environment variable Run the following command to output the paths to all binaries: ```terminal npx prisma -v ``` The output shows that the query engine path comes from the `PRISMA_QUERY_ENGINE_BINARY` environment variable: ```terminal highlight=2;normal Current platform : darwin Query Engine : query-engine d6ff7119649922b84e413b3b69660e2f49e2ddf3 (at /custom/my-query-engine-unix) Migration Engine : migration-engine-cli d6ff7119649922b84e413b3b69660e2f49e2ddf3 (at /myproject/node_modules/@prisma/engines/migration-engine-unix) Introspection Engine : introspection-core d6ff7119649922b84e413b3b69660e2f49e2ddf3 (at /myproject/node_modules/@prisma/engines/introspection-engine-unix) ``` ```terminal highlight=2;normal Current platform : windows Query Engine : query-engine d6ff7119649922b84e413b3b69660e2f49e2ddf3 (at c:\custom\my-query-engine-windows.exe) Migration Engine : migration-engine-cli d6ff7119649922b84e413b3b69660e2f49e2ddf3 (at c:\myproject\node_modules\@prisma\engines\migration-engine-windows.exe) Introspection Engine : introspection-core d6ff7119649922b84e413b3b69660e2f49e2ddf3 (at c:\myproject\node_modules\@prisma\engines\introspection-engine-windows.exe) ``` ### Hosting engines The [`PRISMA_ENGINES_MIRROR`](/orm/reference/environment-variables-reference#prisma_engines_mirror) environment variable allows you to host engine files via a private server, AWS bucket or other cloud storage. This can be useful if you have a custom OS that requires custom-built engines. ```terminal PRISMA_ENGINES_MIRROR=https://my-aws-bucket ``` ## The query engine file The **query engine file** is different for each operating system. It is named `query-engine-PLATFORM` or `libquery_engine-PLATFORM` where `PLATFORM` corresponds to the name of a compile target. Query engine file extensions depend on the platform as well. As an example, if the query engine must run on a [Darwin]() operating system such as macOS Intel, it is called `libquery_engine-darwin.dylib.node` or `query-engine-darwin`. You can find an overview of all supported platforms [here](/orm/reference/prisma-schema-reference#binarytargets-options). The query engine file is downloaded into the `runtime` directory of the generated Prisma Client when `prisma generate` is called. Note that the query engine is implemented in Rust. The source code is located in the [`prisma-engines`](https://github.com/prisma/prisma-engines/) repository. ## The query engine at runtime By default, Prisma Client loads the query engine as a [Node-API library](https://nodejs.org/api/n-api.html). You can alternatively [configure Prisma to use the query engine compiled as an executable binary](#configuring-the-query-engine), which is run as a sidecar process alongside your application. The Node-API library approach is recommended since it reduces the communication overhead between Prisma Client and the query engine. ![Diagram showing the query engine and Node.js at runtime](./query-engine-node-js-at-runtime.png) The query engine is started when the first Prisma Client query is invoked or when the [`$connect()`](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management) method is called on your `PrismaClient` instance. Once the query engine is started, it creates a [connection pool](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool) and manages the physical connections to the database. From that point onwards, Prisma Client is ready to send [queries](/orm/prisma-client/queries/crud) to the database (e.g. `findUnique()`, `findMany`, `create`, ...). The query engine is stopped and the database connections are closed when [`$disconnect()`](/orm/prisma-client/setup-and-configuration/databases-connections/connection-management) is invoked. The following diagram depicts a "typical flow": 1. `$connect()` is invoked on Prisma Client 1. The query engine is started 1. The query engine establishes connections to the database and creates connection pool 1. Prisma Client is now ready to send queries to the database 1. Prisma Client sends a `findMany()` query to the query engine 1. The query engine translates the query into SQL and sends it to the database 1. The query engine receives the SQL response from the database 1. The query engine returns the result as plain old JavaScript objects to Prisma Client 1. `$disconnect()` is invoked on Prisma Client 1. The query engine closes the database connections 1. The query engine is stopped ![Typical flow of the query engine at run time](./typical-flow-query-engine-at-runtime.png) ## Responsibilities of the query engine The query engine has the following responsibilities in an application that uses Prisma Client: - manage physical database connections in connection pool - receive incoming queries from the Prisma Client Node.js process - generate SQL queries - send SQL queries to the database - process responses from the database and send them back to Prisma Client ## Debugging the query engine You can access the logs of the query engine by setting the [`DEBUG`](/orm/prisma-client/debugging-and-troubleshooting/debugging) environment variable to `engine`: ```terminal export DEBUG="engine" ``` You can also get more visibility into the SQL queries that are generated by the query engine by setting the [`query` log level](/orm/reference/prisma-client-reference#log-levels) in Prisma Client: ```ts showLineNumbers const prisma = new PrismaClient({ log: ['query'], }) ``` Learn more about [Debugging](/orm/prisma-client/debugging-and-troubleshooting/debugging) and [Logging](/orm/prisma-client/observability-and-logging/logging). ## Configuring the query engine ### Defining the query engine type for Prisma Client [As described above](#the-query-engine-at-runtime) the default query engine is a Node-API library that is loaded into Prisma Client, but there is also an alternative implementation as an executable binary that runs in its own process. You can configure the query engine type by providing the `engineType` property to the Prisma Client `generator`: ```prisma generator client { provider = "prisma-client-js" engineType = "binary" } ``` Valid values for `engineType` are `binary` and `library`. You can also use the environment variable [`PRISMA_CLIENT_ENGINE_TYPE`](/orm/reference/environment-variables-reference#prisma_client_engine_type) instead. - Until Prisma 3.x the default and only engine type available was `binary`, so there was no way to configure the engine type to be used by Prisma Client and Prisma CLI. - From versions [2.20.0](https://github.com/prisma/prisma/releases/2.20.0) to 3.x the `library` engine type was available and used by default by [activating the preview feature flag](/orm/reference/preview-features/client-preview-features#enabling-a-prisma-client-preview-feature) "`nApi`" or using the `PRISMA_FORCE_NAPI=true` environment variable. ### Defining the query engine type for Prisma CLI Prisma CLI also uses its own query engine for its own needs. You can configure it to use the binary version of the query engine by defining the environment variable [`PRISMA_CLI_QUERY_ENGINE_TYPE=binary`](/orm/reference/environment-variables-reference#prisma_cli_query_engine_type). --- # Under the hood URL: https://www.prisma.io/docs/orm/more/under-the-hood/index This page gives an overview of the Prisma ORM internals and how it works "under the hood". Note that **this page does not contain any practical information that is relevant for _using_ Prisma ORM**. It rather aims at providing a _mental model_ for what the Prisma ORM toolkit _actually_ is and how the different tools that are available to developers are structured. If you're new to using Prisma ORM, be sure to check out the [Quickstart](/getting-started/quickstart-sqlite) and [Introduction](/orm/overview/introduction/what-is-prisma) pages first. ## In this section --- # Upgrade to Prisma ORM 6 URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6 Prisma ORM v6 introduces a number of **breaking changes** when you upgrade from an earlier Prisma ORM version. This guide explains how this upgrade might affect your application and gives instructions on how to handle any changes. ## Upgrade the `prisma` and `@prisma/client` packages to v6 To upgrade to Prisma ORM v6 from an earlier version, you need to update both the `prisma` and `@prisma/client` packages: ```terminal npm install @prisma/client@6 npm install -D prisma@6 ``` ```terminal yarn up prisma@6 @prisma/client@6 ``` ```terminal pnpm upgrade prisma@6 @prisma/client@6 ``` ```terminal bun add @prisma/client@6 bun add prisma@6 --dev ``` :::danger Before you upgrade, check each breaking change below to see how the upgrade might affect your application. ::: ## Breaking changes This section gives an overview of breaking changes in Prisma ORM v6. ### Minimum supported Node.js versions The new minimum supported Node.js versions for Prisma ORM v6 are: - for Node.js 18 the minimum supported version is **18.18.0** - for Node.js 20 the minimum supported version is **20.9.0** - for Node.js 22 the minimum supported version is **22.11.0** There is _no_ official support for Node.js 16, 17, 19 and 21. ### Minimum supported TypeScript version The new minimum supported TypeScript version for Prisma ORM v6 is: **5.1.0**. :::info This schema change only applies to PostgreSQL. If you are using CockroachDB, you do not need to take any action—the schema for implicit m-to-n relationships remains unchanged. ::: ### Schema change for implicit m-n relations on PostgreSQL If you're using PostgreSQL and are defining [implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations) in your Prisma schema, Prisma ORM maintains the [relation table](/orm/prisma-schema/data-model/relations/many-to-many-relations#relation-tables) for you under the hood. This relation table has `A` and `B` columns to represent the tables of the models that are part of this relation. Previous versions of Prisma ORM used to create a _unique index_ on these two columns. In Prisma v6, this unique index is changing to a _primary key_ in order to [simplify for the default replica identity behaviour](https://github.com/prisma/prisma/issues/25196).
Expand for an example As an example, consider the following Prisma schema with an implicit m-n relation between `Post` and `Tag` models: ```prisma model Post { id Int @id @default(autoincrement()) title String categories Tag[] } model Tag { id Int @id @default(autoincrement()) name String posts Post[] } ``` In this case, Prisma ORM maintains the following relation table for you under the hood: ```sql -- CreateTable CREATE TABLE "_PostToTag" ( "A" INTEGER NOT NULL, "B" INTEGER NOT NULL ); -- CreateIndex -- highlight-next-line CREATE UNIQUE INDEX "_PostToTag_AB_unique" ON "_PostToTag"("A", "B"); -- CreateIndex CREATE INDEX "_PostToTag_B_index" ON "_PostToTag"("B"); -- AddForeignKey ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Post"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; ``` In Prisma v6, the `UNIQUE INDEX` is changing into a `PRIMARY KEY`: ```sql -- CreateTable CREATE TABLE "_PostToTag" ( "A" INTEGER NOT NULL, "B" INTEGER NOT NULL, -- highlight-next-line CONSTRAINT "_PostToTag_AB_pkey" PRIMARY KEY ("A","B") ); -- CreateIndex CREATE INDEX "_PostToTag_B_index" ON "_PostToTag"("B"); -- AddForeignKey ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_A_fkey" FOREIGN KEY ("A") REFERENCES "Post"("id") ON DELETE CASCADE ON UPDATE CASCADE; -- AddForeignKey ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_B_fkey" FOREIGN KEY ("B") REFERENCES "Tag"("id") ON DELETE CASCADE ON UPDATE CASCADE; ```
If you're defining implicit m-n relations in your Prisma schema, **the next migration you'll create will contain `ALTER TABLE` statements for _all_ the relation tables** that belong to these relations. These will look similar to this: ```sql -- AlterTable ALTER TABLE "_PostToTag" ADD CONSTRAINT "_PostToTag_AB_pkey" PRIMARY KEY ("A", "B"); -- DropIndex DROP INDEX "_PostToTag_AB_unique"; ``` In order to isolate these schema changes (and not having them bundled with your next migration), **we recommend that you create a new migration _right after_ having upgraded to Prisma v6**: ```terminal npx prisma migrate dev --name upgrade-to-v6 ``` That way, you have a single, dedicated migration that takes care of this schema change and otherwise keeps your migration history clean. ### Full-text search on PostgreSQL The [`fullTextSearch`](/orm/prisma-client/queries/full-text-search) Preview feature is promoted to General Availability only for MySQL. This means that if you're using PostgreSQL and currently make use of this Preview feature, you now need to use the new [`fullTextSearchPostgres`](/orm/prisma-client/queries/full-text-search#enabling-full-text-search-for-postgresql) Preview feature: #### Before ```prisma file=schema.prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" // edit-next-line previewFeatures = ["fullTextSearch"] } ``` #### After ```prisma file=schema.prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" // edit-next-line previewFeatures = ["fullTextSearchPostgres"] } ``` ### Usage of `Buffer` In an effort to improve compatibility between Prisma and new modern JavaScript runtimes, we're gradually moving away from Node.js-specific APIs in favor of standard JavaScript. Prisma v6 replaces the usage of [`Buffer`](https://nodejs.org/api/buffer.html) with [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array) to represent fields of type `Bytes`. Make sure to replace all your occurences of the `Buffer` type with the new `Uint8Array`.
Expand to view how to convert between Buffer and Uint8Array ### Conversion from `Buffer` to `Uint8Array` You can directly use the `Buffer` instance as a `Uint8Array`: ```ts const buffer: Buffer = Buffer.from([1, 2, 3, 4]); const uint8Array: Uint8Array = buffer; // No conversion needed ``` ### Conversion from `Uint8Array` to `Buffer` You can create a `Buffer` from a `Uint8Array` using `Buffer.from`: ```ts const uint8Array: Uint8Array = new Uint8Array([1, 2, 3, 4]); const buffer: Buffer = Buffer.from(uint8Array.buffer); ```
#### Before ```ts import { PrismaClient } from '@prisma/client' async function main() { const prisma = new PrismaClient() await prisma.user.deleteMany() const bytesCreated = await prisma.user.create({ data: { bytes: Buffer.from([1, 2, 3, 4]), }, }) // ^^^^^^^^^^^^^^^^^^^^^^^^^^ // `bytesCreated` used to have type: { // bytes: Buffer // id: number // } for (const bytesFound of await prisma.user.findMany()) { bytesFound.bytes // Buffer [ 1, 2, 3, 4 ] } } main() ``` ```prisma model User { id Int @id @default(autoincrement()) bytes Bytes } ``` #### After ```ts import { PrismaClient } from '@prisma/client' async function main() { const prisma = new PrismaClient() await prisma.user.deleteMany() const bytesCreated = await prisma.user.create({ data: { bytes: Uint8Array.from([1, 2, 3, 4]), }, }) // ^^^^^^^^^^^^^^^^^^^^^^^^^^ // `bytesCreated` now has type: { // bytes: Uint8Array // id: number // } for (const bytesFound of await prisma.user.findMany()) { bytesFound.bytes // Uint8Array [ 1, 2, 3, 4 ] } } main() ``` ```prisma model User { id Int @id @default(autoincrement()) bytes Bytes } ``` ### Removed `NotFoundError` In Prisma v6, we removed the `NotFoundError` in favor of `PrismaClientKnownRequestError` with error code [`P2025`](/orm/reference/error-reference#p2025) in [`findUniqueOrThrow()`](/orm/reference/prisma-client-reference#finduniqueorthrow) and [`findFirstOrThrow()`](/orm/reference/prisma-client-reference#findfirstorthrow). If you've relied on catching `NotFoundError` instances in your code, you need to adjust the code accordingly. #### Before ```ts import { PrismaClient, NotFoundError } from '@prisma/client'; // inside an `async` function try { const user = await prisma.user.findUniqueOrThrow({ where: { id: 42 }, }); console.log(user); } catch (error) { // highlight-start if (error instanceof NotFoundError) { console.error("User not found!"); } // highlight-end else { console.error("Unexpected error:", error); } } ``` #### After ```ts import { PrismaClient, Prisma } from '@prisma/client'; // inside an `async` function try { const user = await prisma.user.findUniqueOrThrow({ where: { id: 42 }, }); console.log(user); } catch (error) { // highlight-start if ( error instanceof Prisma.PrismaClientKnownRequestError && error.code === 'P2025' // Specific code for "record not found" ) { console.error("User not found!"); } // highlight-end else { console.error("Unexpected error:", error); } } ``` ### New keywords that can't be used as model names: `async`, `await`, `using` With this release, you can't use `async`, `await` and `using` as model names any more. ## Preview features promoted to General Availability In this release, we are promoting a number of [Preview](/orm/more/releases#preview) features to [General Availability](/orm/more/releases#generally-available-ga). ### `fullTextIndex` If you use the [full-text index](/orm/prisma-schema/data-model/indexes#full-text-indexes-mysql-and-mongodb) feature in your app, you can now remove `fullTextIndex` from the `previewFeatures` in your Prisma schema: ```prisma generator client { provider = "prisma-client-js" // delete-next-line previewFeatures = ["fullTextIndex"] } ``` ### `fullTextSearch` If you use the [full-text search](/orm/prisma-client/queries/full-text-search) feature with **MySQL** in your app, you can now remove `fullTextSearch` from the `previewFeatures` in your Prisma schema: ```prisma generator client { provider = "prisma-client-js" // delete-next-line previewFeatures = ["fullTextSearch"] } ``` If you are using it with **PostgreSQL**, you need to update the name of the feature flag to `fullTextSearchPostgres`: ```prisma generator client { provider = "prisma-client-js" // edit-next-line previewFeatures = ["fullTextSearchPostgres"] } ``` --- # rejectOnNotFound changes URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5/rejectonnotfound-changes As of Prisma ORM version 5.0.0, the deprecated parameter `rejectOnNotFound` has been removed. Depending on if your project used `rejectOnNotFound` per query or globally, there will be be different ways of updating your code. If you are using the `rejectOnNotFound` parameter on a per-query basis, then follow our steps for [updating your code at the query level](#replacing-rejectonnotfound-enabled-at-the-query-level). If instead you have set up the `rejectOnNotFound` parameter at the client level, you will need to follow [the steps for updating your code at the client level](#replacing-rejectonnotfound-enabled-at-the-client-level). A full list of Prisma ORM 5 changes can be found [in our release notes](https://github.com/prisma/prisma/releases/tag/5.0.0). ## Replacing `rejectOnNotFound` enabled at the query level If you previously enabled `rejectOnNotFound` on a per-query basis, you will need to replace your usage at the _query level_. You can use our `*OrThrow` query variants, `findFirstOrThrow` or `findUniqueOrThrow` instead of supplying the parameter to `findFirst` and `findUnique()`. ### Simple `rejectOnNotFound` usage The following example: ```js prisma.user.findFirst({ where: { name: 'Alice' }, rejectOnNotFound: true, }) ``` needs to be converted to: ```js prisma.user.findFirstOrThrow({ where: { name: 'Alice' }, }) ``` ### `rejectOnNotFound` usage with custom error handler If you use a custom error handler like the following: ```js prisma.user.findFirst({ where: { name: 'Alice' }, rejectOnNotFound: () => new UserNotFoundError(), }) ``` You will need to modify your code to handle the errors thrown by `...OrThrow` methods. ```js try { await prisma.user.findFirstOrThrow({ where: { name: 'Alice' }, }) } catch (err) { if (err.code === 'P2025') { throw new UserNotFoundError() } throw err } ``` If your error handler is used in multiple places, you can also create a reusable error adapter which could then be used within a `.catch()` called on your function. ```js const adaptError = (customThrowFn) => (error) => { if (error.code === 'P2025') { throw customThrowFn() } throw error } const user = await prisma.user.findFirstOrThrow({ where: { name: 'Alice' }, }).catch(adaptError(() => new MyCustomError()) ``` ## Replacing `rejectOnNotFound` enabled at the Client level ### `rejectOnNotFound` via Prisma Client Constructor If you previously enabled `rejectOnNotFound` globally via configuration in the Prisma Client constructor, like in these examples: ```js // Example 1 const prisma = new PrismaClient({ rejectOnNotFound: true, }) // Example 2 const prisma = new PrismaClient({ rejectOnNotFound: { findUnique: true, }, }) ``` You will need to update your codebase to use `findUniqueOrThrow` and `findFirstOrThrow` instead of `findUnique()` and `findFirst`, depending on which calls you would like to throw. ### `rejectOnNotFound` via Prisma Client Constructor with custom error handler If instead you use a custom error handler with the `rejectOnNotFound` property, like these examples: ```js // Example 3 const prisma = new PrismaClient({ rejectOnNotFound: (err) => new Error('something'), }) // Example 4 const prisma = new PrismaClient({ rejectOnNotFound: { findUnique: (err) => new Error('something'), }, }) // Example 5 const prisma = new PrismaClient({ rejectOnNotFound: { findFirst: { User: (err) => new Error('User error'), Post: (err) => new Error('Post error'), }, findUnique: { User: (err) => new Error('User error'), Post: (err) => new Error('Post error'), }, }, }) ``` You will need to update your method usage to `...OrThrow` and then use a [Client Extension](/orm/prisma-client/client-extensions) in order to get the same behavior. As an example, the following extension would give the same behavior in Prisma ORM 5 that `Example 5` gave in Prisma ORM 4 and lower. ```js import { PrismaClient } from '@prisma/client'; const customErrorFunc = async (model, query, args) => { try { await query(args) } catch (error: any) { if (error.code === 'P2025') { throw new Error(`${model} error`) } throw error; } } const prisma = (new PrismaClient()).$extends({ query: { user: { async findFirstOrThrow({ model, query, args }) { return await customErrorFunc(model, query, args) }, async findUniqueOrThrow({ model, query, args }) { return await customErrorFunc(model, query, args) }, }, post: { async findFirstOrThrow({ model, query, args }) { return await customErrorFunc(model, query, args) }, async findUniqueOrThrow({ model, query, args }) { return await customErrorFunc(model, query, args) }, }, }, }) ``` --- # jsonProtocol changes URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5/jsonprotocol-changes As of Prisma ORM version 5.0.0, the new `jsonProtocol` is the default. There are some changes that directly result from this change and a few changes that are related to the new protocol. A full list of Prisma ORM 5 changes can be found [in our release notes](https://github.com/prisma/prisma/releases/tag/5.0.0). ## `jsonProtocol` specific changes Below are changes that result directly from the `jsonProtocol` feature becoming the default in Prisma ORM 5. ### Removal of `jsonProtocol` Preview Feature In Prisma ORM 5, `jsonProtocol` is the default and only protocol in Prisma Client. The `jsonProtocol` Preview feature is no longer needed. Prisma ORM 4 and lower: ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["jsonProtocol"] } ``` Prisma ORM 5: ```prisma generator client { provider = "prisma-client-js" } ``` ### Improved error messages Due to the switch to the new protocol, several error messages have been improved. For example, the following error message in Prisma ORM 4 and below: ```terminal Failed to validate the query: `Unable to match input value to any allowed input type for the field. Parse errors: [Query parsing/validation error at `Mutation.createOneUser.data.UserCreateInput.person.PersonCreateNestedOneWithoutUserInput.create`: Unable to match input value to any allowed input type for the field. Parse errors: [Query parsing/validation error at `Mutation.createOneUser.data.UserCreateInput.person.PersonCreateNestedOneWithoutUserInput.create.PersonCreateWithoutUserInput.hubspot_id`: A value is required but not set., Query parsing/validation error at `Mutation.createOneUser.data.UserCreateInput.person.PersonCreateNestedOneWithoutUserInput.create.PersonUncheckedCreateWithoutUserInput.hubspot_id`: A value is required but not set.], Query parsing/validation error at `Mutation.createOneUser.data.UserUncheckedCreateInput.person`: Field does not exist on enclosing type.]` at `Mutation.createOneUser.data` ``` becomes the following in Prisma ORM 5: ```terminal Invalid `prisma.user.create()` invocation in /Users/prismo/projects/prisma/reproductions/workbench/index.ts:21:36 18 const prisma = new PrismaClient() 19 20 for (const u of userData) { → 21 const user = await prisma.user.create({ data: { email: "eugene.albright@gallaudet.edu", person: { create: { first_name: "William", last_name: "Albright", + hubspot_id: String } } } }) Argument `hubspot_id` must not be null. ``` ## `jsonProtocol` related changes Below are changes that are related to the switch to the new protocol. If you were using the `jsonProtocol` Preview Feature, you most likely ran into these issues. ### Removal of array shortcuts Several array shortcuts were removed as a part of this major update. These shortcuts were a way to add a single element as a value to an array-based operator. #### `OR` operators The following code in Prisma ORM 4 and lower: ```js prisma.user.findMany({ where: { OR: { email: 'foo@example.com' }, }, }) ``` Will need to be changed to the following in Prisma ORM 5: ```js highlight=3;normal prisma.user.findMany({ where: { OR: [{ email: 'foo@example.com' }], }, }) ``` `OR` operators will only accept array values. #### `in` and `notIn` operators Similar to `OR`, `in` and `notIn` require array values. Prisma ORM 4 and lower: ```js prisma.user.findMany({ where: { id: { in: 123 }, }, }) prisma.user.findMany({ where: { id: { notIn: 123 }, }, }) ``` Prisma ORM 5: ```js highlight=4,12;normal prisma.user.findMany({ where: { id: { in: [123], }, }, }) prisma.user.findMany({ where: { id: { notIn: [123], }, }, }) ```
Suggestion for single elements If your `in` and `notIn` values are only one element, you can also update your code to not use these operators at all: ```js highlight=3,9;normal prisma.user.findMany({ where: { id: 123, }, }) prisma.user.findMany({ where: { id: { not: 123 }, }, }) ```
#### `path` argument for filtering on JSON fields in PostgreSQL [When filtering on JSON fields in a PostgreSQL model](/orm/prisma-client/special-fields-and-types/working-with-json-fields#filter-on-a-json-field-simple) the `path` argument now only accepts an array. When using the following schema: ```prisma model User { id String @id settings Json } ``` Prisma ORM 4 and lower: ```js prisma.user.findMany({ where: { settings: { path: 'someSetting', equals: someValue, }, }, }) ``` Prisma ORM 5: ```js highlight=4;normal prisma.user.findMany({ where: { settings: { path: ['someSetting'], equals: someValue, }, }, }) ``` Note: This `path` argument change only affects PostgreSQL databases. MySQL databases are not affected as they use a different syntax. #### Scalar lists [Scalar list](/orm/prisma-schema/data-model/models#scalar-fields) values must be arrays in all operations. With the following schema: ```prisma model Post { id String @id @default(uuid()) tags String[] } ``` Prisma ORM 4 and lower: ```js prisma.post.create({ data: { tags: 'databases', }, }) prisma.post.findMany({ where: { tags: 'databases', }, }) ``` Prisma ORM 5: ```js highlight=3,9;normal prisma.post.create({ data: { tags: ['databases'], }, }) prisma.post.findMany({ where: { tags: ['databases'], }, }) ``` #### Composite lists Operations on lists of [Composite types](/orm/prisma-schema/data-model/models#defining-composite-types) (for [MongoDB](/orm/overview/databases/mongodb)) now only accept array values. With the following schema: ```prisma model Post { id String @id @default(uuid()) commentsList Comment[] } type Comment { text String } ``` Prisma ORM 4 and lower: ```js prisma.post.findMany({ where: { commentsList: { equals: { text: 'hello' }, }, }, }) ``` Prisma ORM 5: ```js highlight=4;normal prisma.post.findMany({ where: { commentsList: { equals: [{ text: 'hello' }], }, }, }) ```
Shorthand notation usage If you use the shorthand notation and exclude `equals`, you still must supply an array value for composite list fields. Prisma 4 and lower: ```js prisma.post.create({ data: { commentsList: { text: 'hello' }, }, }) prisma.post.findMany({ where: { commentsList: { text: 'hello' }, }, }) ``` Prisma 5: ```js highlight=3,8;normal prisma.post.create({ data: { commentsList: [{ text: 'hello' }], }, }) prisma.post.findMany({ where: { commentsList: [{ text: 'hello' }], }, }) ```
--- # Upgrade to Prisma ORM 5 URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5/index Prisma ORM 5.0.0 introduces a number of changes, including the usage of our new JSON Protocol, [which make Prisma Client faster by default](https://www.prisma.io/blog/prisma-5-f66prwkjx72s). A full list of these changes can be found [in our release notes](https://github.com/prisma/prisma/releases/tag/5.0.0). This guide explains how upgrading might affect your application and gives instructions on how to handle breaking changes within Prisma ORM 5. ## Upgrade the `prisma` and `@prisma/client` packages to version 5 To upgrade to Prisma ORM 5 from an earlier version, you need to update both the `prisma` and `@prisma/client` packages. ```terminal npm install @prisma/client@5 npm install -D prisma@5 ``` ```terminal yarn up prisma@5 @prisma/client@5 ``` ```terminal pnpm upgrade prisma@5 @prisma/client@5 ``` Before you upgrade, check each breaking change below to see how the upgrade might affect your application. ## Version changes Prisma ORM 5 includes some minimum version changes for Node.js, TypeScript, and PostgreSQL. To use Prisma version 5.0.0 and up, you will need to have at least the minimum versions below: See our [system requirements](/orm/reference/system-requirements) for all minimum version requirements. ### Node.js minimum version change From Prisma ORM version 5.0.0, the minimum version of Node.js supported is 16.13.0. If your project uses an earlier version of Node.js, you will need to upgrade it. Node.js v16.x is reaching [end-of-life on 11 September 2023](https://nodejs.org/en/blog/announcements/nodejs16-eol) in order to coincide with the end-of-life of OpenSSL 1.1.1. For that reason, we recommend upgrading to the current Node.js LTS, v18.x. Please note that Prisma ORM 5 will be the last major version of Prisma ORM to support Node.js v16. ### TypeScript minimum version change From Prisma ORM version 5.0.0, the minimum version of TypeScript supported is 4.7. If your project uses an earlier version of TypeScript, you will need to upgrade it. ### PostgreSQL minimum version change From Prisma ORM version 5.0.0, the minimum version of PostgreSQL supported is 9.6. If your project uses an earlier version of PostgreSQL, you will need to upgrade it. While Prisma ORM supports PostgreSQL versions 9.6 and above, we **strongly** recommend updating to a version that is currently supported and still receiving updates. Please check [PostgreSQL's versioning policy](https://www.postgresql.org/support/versioning/) to determine which versions are currently supported. ### Prisma Client embedded SQLite version updated With Prisma ORM version 5.0.0, we have upgraded the embedded version of SQLite from `3.35.4` to `3.41.2`. We did not see any breaking changes and don't anticipate any changes needed in user projects, but if you are using SQLite, especially with raw queries that might go beyond Prisma ORM's functionality, make sure to check [the SQLite changelog](https://www.sqlite.org/changes.html). ## Primary changes This section gives an overview of the main breaking changes in Prisma ORM 5. ### Removal of `rejectOnNotFound` parameter With Prisma ORM 5, the deprecated parameter `rejectOnNotFound` has been removed. Depending on if your project used `rejectOnNotFound` per query or globally, there will be be different ways of updating your code. If you are using the `rejectOnNotFound` parameter on a per-query basis, then follow our steps for [updating your code at the query level](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5/rejectonnotfound-changes#replacing-rejectonnotfound-enabled-at-the-query-level). If instead you have set up the `rejectOnNotFound` parameter at the client level, you will need to follow [the steps for updating your code at the client level](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5/rejectonnotfound-changes#replacing-rejectonnotfound-enabled-at-the-client-level). ### `jsonProtocol` out of Preview The `jsonProtocol` preview feature is now Generally Available. This new protocol leads to [significantly improved startup times](https://www.prisma.io/blog/prisma-5-f66prwkjx72s#improved-startup-performance-in-prisma-client) when compared to our previous GraphQL-based protocol. When upgrading to Prisma ORM 5, make sure to remove `jsonProtocol` from your preview features, if added. Prisma ORM 4 and lower: ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["jsonProtocol"] } ``` Prisma ORM 5: ```prisma generator client { provider = "prisma-client-js" } ``` Please review our [jsonProtocol changes guide](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5/jsonprotocol-changes) to learn how to update your app to account for the new protocol in Prisma ORM 5. You will need to: - [Remove the `jsonProtocol` Preview Feature](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5/jsonprotocol-changes#removal-of-jsonprotocol-preview-feature) - [Remove usage of certain array shortcuts](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5/jsonprotocol-changes#removal-of-array-shortcuts) ### Removal of array shortcuts Prisma ORM 5 drops support for a number of "array shortcuts". These shortcuts were a way to add a single element as a value to an array-based operator instead of wrapping that one element in an array. To make our typings more consistent and logical and to conform to the new JSON Protocol, we now require array values for these operators. In most cases, the fix will be as simple as wrapping the existing value in an array. The shortcuts removed in Prisma ORM 5 are: - [`OR` shortcuts](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5/jsonprotocol-changes#or-operators) - [`in` and `notIn` shortcuts](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5/jsonprotocol-changes#in-and-notin-operators) - [PostgreSQL JSON `path` field shortcuts](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5/jsonprotocol-changes#path-argument-for-filtering-on-json-fields-in-postgresql) - [Scalar list shortcuts](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5/jsonprotocol-changes#scalar-lists) - [MongoDB Composite list shortcuts](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5/jsonprotocol-changes#composite-lists) While `OR`, `in`, and `notIn` operators are affected, `AND` and `NOT` are not affected by this change. ### `cockroachdb` provider is now required when connecting to a CockroachDB database With Prisma ORM version 5.0.0, we require the `cockroachdb` provider to be used when connecting to CockroachDB databases. Previously, we had accepted `postgresql` as well, but we are removing that option. If you were using [native database types](/orm/reference/prisma-schema-reference#postgresql) and also the `postgresql` provider, you will need to [baseline your database](/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-cockroachdb) from PostgreSQL to CockroachDB: 1. Backup your existing `schema.prisma` file (e.g. use version control) 2. Update your `datasource` provider from `postgresql` to `cockroachdb` 3. Use `npx prisma db pull --force` in order to overwrite your existing Prisma schema (including native types) to those that are on your CockroachDB instance. 4. Review changes between your Prisma schema backup and the new Prisma schema generated by `db pull`. You can either use the new schema as is, or update it to include your preferred spacing, comments, etc. 5. Delete your existing migrations. We will be [performing a baseline](/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-cockroachdb) in order to make your local setup agree with your existing CockroachDB instance. 6. Perform the [baselining steps](/getting-started/setup-prisma/add-to-existing-project/relational-databases/baseline-your-database-typescript-cockroachdb). After these steps, you'll have migrated successfully from the `postgresql` provider to the `cockroachdb` provider! ### Removal of `runtime/index.js` from generated client The `runtime/index.js` file has been removed from Prisma Client. #### Using public APIs from `@prisma/client/runtime` Importing from `@prisma/client/runtime` is no longer available in Prisma ORM 5. If you were using public APIs available in this namespace before, you can instead import `Prisma` and access them. For example: ```js import { Decimal, NotFoundError } from '@prisma/client/runtime' const num = new Decimal(24.454545) const notFound = new NotFoundError() ``` will need to be changed to ```js import { Prisma } from '@prisma/client' const num = new Prisma.Decimal(24.454545) const notFound = new Prisma.NotFoundError() ``` #### Using private APIs for a specific runtime We highly discourage the use of internal private APIs as they can change without warning and are not guaranteed to be supported. If your usage requires a private API that was previous available [please reach out to us on GitHub.](https://github.com/prisma/prisma/discussions/new?category=q-a) ### Generated type changes #### Changes to `RelationFilterInput` to account for nullability Prior to Prisma ORM 5, there was a long-standing bug that caused nullable reverse relations to not be marked as nullable in our generated types. For example, take the following schema: ```prisma model User { id Int @id addressId Int @unique address Address @relation(fields: [addressId], references: [id]) post Post[] } model Address { id Int @id user User? } model Post { id Int @id userId Int user User @relation(fields: [userId], references: [id]) } ``` In the generated types, `Address.user` and `Post.user` would use the same type, `UserRelationFilter`. This is obviously unintended as `Address.user` is nullable while `Post.user` is not. In Prisma ORM 5, the type of `Address.user` would be `UserNullableRelationFilter`, resolving this issue. If you import generated types in your code, you will need to update instances like this to utilize the new `Nullable` types. #### Changes to `UncheckedUpdateManyInput` to avoid name collisions In certain instances it was possible for name collisions to occur when one model had two foreign keys to two other models that had the same property name for the reverse relation. As an example, the following schema: ```prisma model Invoice { InvoiceId Int @id @default(autoincrement()) invoice_items InvoiceItem[] } model InvoiceItem { InvoiceLineId Int @id @default(autoincrement()) InvoiceItemInvoiceId Int @map("InvoiceId") invoices Invoice @relation(fields: [InvoiceItemInvoiceId], references: [InvoiceId]) TrackId Int tracks Track @relation(fields: [TrackId], references: [TrackId]) } model Track { TrackId Int @id @default(autoincrement()) Name String invoice_items InvoiceItem[] } ``` Would lead to conflicting names between the two relations on `InvoiceItem`. The reverse relations, that is `Invoice.invoice_items` and `Track.invoice_items` would both get the type `InvoiceItemUncheckedUpdateManyWithoutInvoice_itemsInput`. In Prisma ORM 5, this is resolved and Prisma Client will generate `InvoiceItemUncheckedUpdateManyWithoutInvoicesInput` and `InvoiceItemUncheckedUpdateManyWithoutTracksInput` respectively. If you import generated types in your code, you will need to update instances like this to the corrected types. ## Other changes The following changes may cause an application to initially throw an error message after upgrading to Prisma ORM 5. Fortunately, they are easy to solve, as the underlying functionality has been removed for a while or the change is a simple string replace. ### Removal of deprecated Prisma CLI flags Several deprecated CLI flags have been removed. All following flags are from previous APIs and are no longer needed: - `--preview-feature` used in `db execute`, `db seed`, and `db diff` - `--experimental` and `--early-access-feature` used in `migrate` - `--force`/`-f` used in `db push` - `--experimental-reintrospection` and `--clean` used in `db pull` The outdated use of `db push --force` can be replaced with the newer implementation `db push --accept-data-loss`. All other flags are from previous APIs and are no longer needed. ### Removal of the `beforeExit` hook from the library engine The `beforeExit` hook has been removed from the Prisma ORM library engine. While this functionality is still required for the Prisma ORM binary engine in order to run last minute queries or perform shutdown related operations, it provides no benefit over native Node.js exit hooks in the library engine. Instead of this hook we recommend using built-in Node.js exit events. The following code with Prisma ORM 4: ```js const exitHandler = () => { // your exit handler code } prisma.$on('beforeExit', exitHandler) ``` Could become: ```js const exitHandler = () => { // your exit handler code } process.on('exit', exitHandler) process.on('beforeExit', exitHandler) process.on('SIGINT', exitHandler) process.on('SIGTERM', exitHandler) process.on('SIGUSR2', exitHandler) ``` If you're using the `beforeExit` hook in NestJS, you can upgrade to Prisma ORM 5 by removing the custom `enableShutdownHooks` method in your service: ```diff file="prisma.service.ts" @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit { async onModuleInit() { await this.$connect() } - async enableShutdownHooks(app: INestApplication) { - this.$on('beforeExit', async () => { - await app.close() - }) - } } ``` Instead, use the built-in `enableShutdownHooks` method in NestJS if you need to handle lifecycle events: ```diff file="main.ts" - prismaService.enableShutdownHooks(app) + app.enableShutdownHooks() ``` ### Removal of deprecated `prisma2` executable When we released Prisma ORM 2, the `prisma2` executable was used in order to differentiate from Prisma 1. In a later release, the `prisma2` cli took over the `prisma` executable name. Needless to say, the `prisma2` executable has been deprecated for some time and is now removed. If your scripts use Prisma CLI as `prisma2`, please replace it with simply `prisma`. ### Removal of deprecated `experimentalFeatures` property The `previewFeatures` field of the [generator block](/orm/reference/prisma-schema-reference#fields-1) used to be called `experimentalFeatures`. We are removing that deprecated property. In Prisma ORM 5, you will need to update references of `experimentalFeatures` to `previewFeatures` manually or use the new code action in the Prisma VSCode extension. ### `migration-engine` renamed to `schema-engine` The engine responsible for commands like `prisma migrate` and `prisma db` has been renamed from `migration-engine` to `schema-engine` to better describe its use. For many users, no changes will be required. However, if you need to explicitly include or exclude this engine file, or refer to the engine name for any other reason, you will need to update your code references. #### Example with the Serverless Framework One example we have seen is projects using the Serverless Framework. In these instances, you will need to update any patterns that reference `migration-engine` to instead reference `schema-engine`. ```yaml highlight=6;delete|7;add package: patterns: - '!node_modules/.prisma/client/libquery_engine-*' - 'node_modules/.prisma/client/libquery_engine-rhel-*' - '!node_modules/prisma/libquery_engine-*' -- '!node_modules/prisma/migration-engine-*' -- '!node_modules/prisma/schema-engine-*' ```
Serverless Framework pattern suggestion The [recommended rule from our documentation](/orm/prisma-client/deployment/serverless/deploy-to-aws-lambda#lambda-functions-with-arm64-architectures) is not affected by this change as it excludes all non desired engine files. ```yaml highlight=6;normal package: patterns: - '!node_modules/.prisma/client/libquery_engine-*' - 'node_modules/.prisma/client/libquery_engine-rhel-*' - '!node_modules/prisma/libquery_engine-*' -- '!node_modules/@prisma/engines/**' ```
Enjoy Prisma ORM 5! --- # Upgrade to Prisma ORM 4 URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-4 Prisma ORM 4 introduces a number of **breaking changes** when you upgrade from an earlier Prisma ORM version. This guide explains how this upgrade might affect your application and gives instructions on how to handle any changes. ## Breaking changes This section gives an overview of breaking changes in Prisma ORM 4, grouped under [general changes](#general-changes) that affect both the Prisma Schema and Prisma Client, [Schema changes](#schema-changes) and [Client changes](#client-changes). We recommend that you first address any Prisma schema validation errors, then pull your database to reflect new Prisma schema capabilities, and finally fix any type errors in Prisma Client and validate by running your test suite. ### Upgrade your Prisma Schema 1. Carefully skim the list of changes and check if you are impacted by a breaking change. 2. Review the Prisma schema validation errors (via `npx prisma validate`, or via the Prisma VS Code extension). 1. If you don't have validation errors, continue with step 3. 2. If you have validation errors: 1. Try to map the validation error to a change from the list below to understand which change caused the invalid Prisma schema, and read the linked instructions for how to upgrade. It can only come from: - [Explicit unique constraints for 1:1 relations](#explicit-unique-constraints-on-one-to-one-relations) - [Removed support for usage of `references` on implicit many-to-many relations](#disallow-references-syntax-for-implicit-many-to-many-relations) - [Enforced uniqueness of referenced fields in the `references` argument in one-to-one and one-to-many relations for MySQL and MongoDB](#enforced-use-of-unique-or-id-attribute-for-one-to-one-and-one-to-many-relations-mysql-and-mongodb) - Removal of undocumented support for the `type` alias - Removal of the `sqlite` protocol for SQLite URLs - [Better grammar for string literals](#better-grammar-for-string-literals) 3. Repeat until your Prisma schema is valid. 4. Run `npx prisma db pull` to upgrade the Prisma schema to all new capabilities (e.g. `extendedIndexes`). 5. Review changes of the Prisma schema and verify validity. 6. Continue with Prisma Client steps. ### Upgrade your use of Prisma Client 1. Carefully skim the [list of changes](#client-changes) to understand if you are impacted by a breaking change. 1. If yes, read the detailed upgrade instructions. 2. If no, proceed with 2. 2. Some API changes in Prisma Client are impacting runtime behavior, so please run your test suite. Enjoy Prisma ORM 4! ### General changes This section includes changes that affect both the Prisma Schema and Prisma Client. #### Node.js minimum version change From Prisma ORM version 4.0.0, the minimum version of Node.js that we support is 14.17.x. If you use an earlier version of Node.js, you will need to update it. See our [system requirements](/orm/reference/system-requirements) for all minimum version requirements. ### Schema changes This section includes changes that affect the Prisma Schema. #### Index configuration In Prisma ORM 4, the `extendedIndexes` Preview feature will now become generally available. This includes the following index configuration options: - Length configuration of indexes, unique constraints and primary key constraints for MySQL (in Preview in versions 3.5.0 and later) - Sort order configuration of indexes, unique constraints and primary key constraints (in Preview in versions 3.5.0 and later) - New index types for PostgreSQL: Hash (in Preview in versions 3.6.0 and later) and GIN, GiST, SP-GiST and BRIN (in Preview in versions 3.14.0 and later) - Index clustering for SQL Server (in Preview in versions 3.13.0 and later) See our documentation on [Index configuration](/orm/prisma-schema/data-model/indexes#index-configuration) for more details of these features. ##### Upgrade path These can all be breaking changes if you were previously configuring these properties at the database level. In this case, you will need to: 1. Upgrade to the new Prisma ORM 4 packages following [these instructions](#upgrade-the-prisma-and-prismaclient-packages-to-version-4) 1. Run `npx prisma db pull` afterwards to retrieve any existing configuration of indexes and constraints. This needs to be done before running any `npx prisma db push` or `npx prisma migrate dev` command, or you may lose any configuration that was defined in the database but not previously represented in the Prisma schema. For more details, see the [Upgrading from previous versions](/orm/prisma-schema/data-model/indexes#upgrading-from-previous-versions) section of our index configuration documentation. #### Scalar list defaults For database connectors that support scalar lists (PostgreSQL, CockroachDB and MongoDB), Prisma ORM 4 introduces the ability to set a default value in your Prisma schema with the `@default` attribute: ```prisma highlight=4;normal model User { id Int @id @default(autoincrement()) posts Post[] //highlight-next-line favoriteColors String[] @default(["red", "yellow", "purple"]) } ``` ```prisma highlight=4;normal model User { id String @id @default(auto()) @map("_id") @db.ObjectId posts Post[] //highlight-next-line favoriteColors String[] @default(["red", "yellow", "purple"]) } ``` ##### Upgrade path This is a breaking change if you previously had defaults defined for scalar lists at the database level. In this case, you will need to: 1. Upgrade to the new Prisma ORM 4 packages following [these instructions](#upgrade-the-prisma-and-prismaclient-packages-to-version-4) 1. Run `npx prisma db pull` afterwards to retrieve any existing configuration of indexes and constraints. This needs to be done before running any `npx prisma db push` or `npx prisma migrate dev` command, or you will lose any defaults that are defined in the database but not previously represented in the Prisma schema. #### Explicit `@unique` constraints on one-to-one relations When using one-to-one relations in Prisma ORM 4, you will need to explicitly add the `@unique` attribute to the relation scalar field. For example, for this one-to-one relation between a `User` and a `Profile` model, you will need to add the `@unique` attribute to the `profileId` field: ```prisma model User { id Int @id @default(autoincrement()) profile Profile? @relation(fields: [profileId], references: [id]) profileId Int? @unique // <-- include this explicitly } model Profile { id Int @id @default(autoincrement()) user User? } ``` ```prisma model User { id String @id @default(auto()) @map("_id") @db.ObjectId profile Profile? @relation(fields: [profileId], references: [id]) profileId String? @unique @db.ObjectId // <-- include this explicitly } model Profile { id String @id @default(auto()) @map("_id") @db.ObjectId user User? } ``` ##### Upgrade path After you upgrade to Prisma ORM 4, any one-to-one relations without a `@unique` attribute on the relation scalar will trigger a validation error. To upgrade, you will need to: 1. Upgrade to the new Prisma ORM 4 packages following [these instructions](#upgrade-the-prisma-and-prismaclient-packages-to-version-4) 1. Manually fix the validation errors in your Prisma schema by adding the explicit `@unique` or `@id` attribute to your data model. 1. Push the changes to your database using `prisma db push` for MongoDB or `prisma migrate dev` for MySQL. #### Enforced use of `@unique` or `@id` attribute for one-to-one and one-to-many relations (MySQL and MongoDB) When you use one-to-one and one-to-many relations in Prisma ORM 4, you will need to use a `@unique` attribute on the relation field to guarantee that the singular side(s) of the relation has only one record. This is now enforced for MySQL and MongoDB, bringing them into line with other connectors. Missing `@unique` attributes will now trigger a validation error. In the following example of a _one-to-many relation_ between a `User` and `Post` model, the `@unique` attribute must be added to the `email` field: ```prisma model User { id Int @id @default(autoincrement()) email String @unique // <-- we enforce this attribute posts Post[] } model Post { id Int @id @default(autoincrement()) authorEmail String author User @relation(fields: [authorEmail], references: [email]) } ``` ```prisma model User { id Int @id @default(auto()) @map("_id") @db.ObjectId email String @unique // <-- we enforce this attribute posts Post[] } model Post { id Int @id @default(auto()) @map("_id") @db.ObjectId authorEmail String author User @relation(fields: [authorEmail], references: [email]) } ``` In the following example of a _one-to-one relation_ between a `User` and `Profile` model, the `@unique` attribute must be added to the `email` field: ```prisma model User { id Int @id @default(autoincrement()) email String @unique // <- we enforce this unique attribute profile Profile @relation(fields: [profileId], references: [id]) profileId Int } model Profile { id Int @id @default(autoincrement()) userEmail String? @unique user User? } ``` ```prisma model User { id Int @id @default(auto()) @map("_id") @db.ObjectId email String @unique // <- we enforce this unique attribute profile Profile @relation(fields: [profileId], references: [id]) profileId Int @db.ObjectId } model Profile { id Int @id @default(auto()) @map("_id") @db.ObjectId userEmail String? @unique user User? @relation(fields: [userEmail], references: [email]) } ``` ##### Upgrade path After you upgrade to Prisma ORM 4, any one-to-one or one-to-many relations without a `@unique` or `@id` attribute on the relation field will trigger a validation error. To upgrade, you will need to: 1. Upgrade to the new Prisma ORM 4 packages following [these instructions](#upgrade-the-prisma-and-prismaclient-packages-to-version-4) 1. Manually fix the validation errors in your Prisma schema. Alternatively, if you have an up-to-date live database, running `npx prisma db pull` will add the `@unique` attributes automatically. #### Disallow `references` syntax for implicit many-to-many relations When using [implicit many-to-many relations](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations) in Prisma ORM 4, you will no longer be able to use the `references` argument, which was previously optional. For example, the following relation would now trigger a validation error: ```prisma file=schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) categories Category[] @relation("my-relation", references: [id]) // <-- validation error } model Category { id Int @id @default(autoincrement()) posts Post[] @relation("my-relation", references: [id]) // <-- validation error } ``` Instead, you can write: ```prisma file=schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) categories Category[] @relation("my-relation") } model Category { id Int @id @default(autoincrement()) posts Post[] @relation("my-relation") } ``` This is because the only valid value for `references` was `id`, so removing this argument makes it clearer what can and cannot be changed. ##### Upgrade path After you upgrade to Prisma ORM 4, any implicit many-to-many relations with a `references` argument will trigger a validation error. To upgrade, you will need to: 1. Upgrade to the new Prisma ORM 4 packages following [these instructions](#upgrade-the-prisma-and-prismaclient-packages-to-version-4) 1. Manually fix the validation errors in your Prisma schema. Alternatively, if you have an up-to-date live database, running `npx prisma db pull` will remove the `references` arguments automatically. #### Better grammar for string literals String literals in your Prisma Schema now need to follow the same rules as strings in JSON. This mostly changes the escaping of some special characters. More details can be found in [the JSON specification](https://www.ietf.org/rfc/rfc4627.txt) or on the [JSON website](https://www.json.org/json-en.html). ##### Upgrade path This is a breaking change for some existing schemas. After you upgrade to Prisma ORM 4, incorrectly escaped characters will trigger a validation error. To upgrade, you will need to: 1. Upgrade to the new Prisma ORM 4 packages following [these instructions](#upgrade-the-prisma-and-prismaclient-packages-to-version-4) 1. Manually fix the validation errors in your Prisma schema. ### Client changes This section includes changes that affect Prisma Client. #### Raw query type mapping: scalar values are now deserialized as their correct JavaScript types In versions 3.14.x and 3.15.x, [raw query type mapping](/orm/prisma-client/using-raw-sql/raw-queries#raw-query-type-mapping) was available with the Preview feature `improvedQueryRaw`. In version 4.0.0, we have made raw query type mapping Generally Available. You do not need to use `improvedQueryRaw` to get this functionality in versions 4.0.0 and later. Raw queries now deserialize scalar values to their corresponding JavaScript types. Note that Prisma ORM infers types from the values themselves and not from the Prisma Schema types. Example query and response: ```ts const res = await prisma.$queryRaw`SELECT bigint, bytes, decimal, date FROM "Table";` console.log(res) // [{ bigint: BigInt("123"), bytes: Buffer.from([1, 2]), decimal: new Prisma.Decimal("12.34"), date: Date("") }] ``` ##### Upgrade path From version 4.0.0, some data types returned by `queryRaw` or `queryRawUnsafe` are different, as follows: | Data type | Before version 4.0.0 | From version 4.0.0 | | ---------- | --------------------- | --------------------- | | `DateTime` | Returned as `String` | Returned as `Date` | | `Numeric` | Returned as `Float` | Returned as `Decimal` | | `Bytes` | Returned as `String` | Returned as `Buffer` | | `Int64` | Returned as `Integer` | Returned as `BigInt` | If you use `queryRaw` or `queryRawUnsafe` to return any of the above data types, then you must change your code to handle the new types. For example, if you return `DateTime` data, then you need to take into account the following: - You no longer need to manually instantiate a `DateTime` object for the returned data. - If your code currently uses the returned `String` data, then you now need to convert the `DateTime` object to a `String`. You must make equivalent code changes for the other data types in the table above. #### Raw query mapping: PostgreSQL type-casts In versions 3.14.x and 3.15.x, [raw query type mapping](/orm/prisma-client/using-raw-sql/raw-queries#raw-query-type-mapping) was available with the Preview feature `improvedQueryRaw`. In version 4.0.0, we have made raw query type mapping Generally Available. You do not need to use `improvedQueryRaw` to get this functionality in versions 4.0.0 and later. Before version 4.0.0, many PostgreSQL type-casts did not work. We have tightened the type coercion rules so that all type-casts now work. As a result, some implicit casts now fail. ##### Upgrade path We recommend that you re-test your use of `$queryRaw` to ensure that the types you pass into your raw queries match the types that PostgreSQL expects. For example, in version 4.0.0, the following query fails: ```js await prisma.$queryRaw`select length(${42});` // ERROR: function length(integer) does not exist // HINT: No function matches the given name and argument types. You might need to add explicit type casts. ``` This is because PostgreSQL’s `length` function expects `text` as input. Prisma ORM used to silently coerce `42` to `text`, but does not do this in version 4.0.0. To fix this, explicitly cast `42` to `text` as follows: ```js await prisma.$queryRaw`select length(${42}::text);` ``` #### Raw query mapping: PostgreSQL and JavaScript integers In versions 3.14.x and 3.15.x, [raw query type mapping](/orm/prisma-client/using-raw-sql/raw-queries#raw-query-type-mapping) was available with the Preview feature `improvedQueryRaw`. In version 4.0.0, we have made raw query type mapping Generally Available. You do not need to use `improvedQueryRaw` to get this functionality in versions 4.0.0 and later. Prisma ORM sends JavaScript integers to PostgreSQL as `INT8`. This might conflict with your user-defined functions that accept only `INT4` as input. ##### Upgrade path If you use `$queryRaw` or parametrized `$queryRawUnsafe`queries with a PostgreSQL database, do one of the following: - Update the input types of any integers in your user-defined functions to `INT8`, or - Cast any integers in your query parameters to `INT4`. #### `DbNull`, `JsonNull` and `AnyNull` are now objects JavaScript `null` is ambiguous for JSON columns, so Prisma ORM uses `DbNull`, `JsonNull`, and `AnyNull` to distinguish between the database `NULL` value and the JSON `null` value. Before version 4.0.0, `DbNull`, `JsonNull`, and `AnyNull` were string constants. From version 4.0.0, they are objects. See [Filtering by null values](/orm/prisma-client/special-fields-and-types/working-with-json-fields#filtering-by-null-values) for more information. ##### Upgrade path 1. If you use literal strings to address these values, then you must replace them with the following named constants: - `DbNull`: replace with `Prisma.DbNull` - `JsonNull`: replace with `Prisma.JsonNull` - `AnyNull`: replace with `Prisma.AnyNull` If you already use these named constants, then you do not need to take any action. 1. If you now get a type error when you pass `Prisma.DbNull` as the value of a JSON field, then this probably indicates a bug in your code that our types did not catch before version 4.0.0. The field where you tried to store `DbNull` is probably not nullable in your schema. As a result, a literal `DbNull` string was stored in the database instead of `NULL`. 1. You might now encounter a type error or runtime validation error when you use `Prisma.DbNull`, `Prisma.JsonNull`, or `Prisma.AnyNull` with MongoDB. This was never valid, but was silently accepted prior to Prisma ORM 4. You need to review your data and change these fields to `null`. 1. If you pass in dynamic JSON to a JSON column in Prisma Client (for example `prisma.findMany({where: { jsonColumn: someJson } })`), then you must check that `someJson`cannot be the string "DBNull", "JsonNull", or "AnyNull". If it is any of these values, then the query will return different results in version 4.0.0. #### Default fields on composite types in MongoDB From version 4.0.0, if you carry out a database read on a composite type when all of the following conditions are true, then Prisma Client inserts the default value into the result. Conditions: - A field on the composite type is required, and - this field has a default value, and - this field is not present in the returned document or documents. This behavior is now consistent with the behavior for model fields. To learn more, see [Default values for required fields on composite types](/orm/prisma-client/special-fields-and-types/composite-types#default-values-for-required-fields-on-composite-types). ##### Upgrade path If you currently rely on a return value of `null`, then you need to refactor your code to handle the default value that is now returned in Prisma ORM 4. #### Rounding errors on big numbers in SQLite SQLite is a loosely-typed database. If your schema has a field with type `Int`, then Prisma ORM prevents you from inserting a value larger than an integer. However, nothing prevents the database from directly accepting a bigger number. These manually-inserted big numbers cause rounding errors when queried. To avoid this problem, Prisma ORM version 4.0.0 and later checks numbers on the way out of the database to verify that they fit within the boundaries of an integer. If a number does not fit, then Prisma ORM throws a P2023 error, such as: ``` Inconsistent column data: Conversion failed: Value 9223372036854775807 does not fit in an INT column, try migrating the 'int' column type to BIGINT ``` ##### Upgrade path If you use Prisma ORM in conjunction with SQLite, then you need to find any code that queries `Int` fields and ensure that it handles any P2023 errors that might be returned. #### Prisma ORM no longer exports `Prisma.dmmf.schema` into the generated Prisma Client From version 4.0.0, Prisma ORM no longer exports `Prisma.dmmf.schema` into the generated Prisma Client. This makes the generated Prisma Client much more efficient, and also avoids some memory leaks with Jest. Note: - This change does not affect the DMMF that Prisma ORM passes to the generators. - You can use `getDmmf()`from `@prisma/internals` to access the schema property. - We still export `Prisma.dmmf.datamodel` into the generated Prisma Client. ## Upgrade the `prisma` and `@prisma/client` packages to version 4 To upgrade to Prisma ORM 4 from an earlier version, you need to update both the `prisma` and `@prisma/client` packages. Both the `prisma` and `@prisma/client` packages install with a caret `^` in their version number. This allows upgrades to new minor versions, but not major versions, to safeguard against breaking changes. To ignore the caret `^` and upgrade across major versions, you can use the `@4` tag when you upgrade with `npm`, or `yarn`: Before you upgrade, check each **breaking change** to see how the upgrade might affect your application. ```terminal npm install prisma@4 @prisma/client@4 ``` ```terminal yarn up prisma@4 @prisma/client@4 ``` ## Video guide For a video walkthrough of the upgrade process and examples of upgrade scenarios, see our recorded livestream on upgrading to Prisma ORM 4:
--- # Named constraints upgrade path URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/named-constraints After upgrading to Prisma ORM 3, the default naming convention for constraint and index names will change and your primary and foreign key names will now be part of the schema for databases that support them. Therefore the meaning of your existing Prisma schema will change. Before you continue to evolve your schema and your database, you should decide which names for constraints and indexes you want to use on your project going forward. You can either keep the names as they exist in your database or you can switch to use the names generated by Prisma ORM, which follow the new naming convention. This page describes the manual upgrade steps that you need to perform after upgrading to Prisma ORM 3. You can pick either of the two options: - **Option 1**: [I want to maintain my existing constraint and index names](#option-1-i-want-to-maintain-my-existing-constraint-and-index-names) - **Option 2**: [I want to use Prisma ORM's default constraint and index names](#option-2-i-want-to-use-prisma-orms-default-constraint-and-index-names) ## Option 1: I want to maintain my existing constraint and index names If you want to keep your database unchanged and keep the existing names for constraints and indexes you need to pull them into your schema so Prisma ORM is aware of them. Reasons to keep your existing names might be: - Naming conventions you have to follow - Other tooling relying on the names - Personal preference To keep existing names, run `prisma db pull` against the target environment. This will result in all names that do not match Prisma ORM's naming convention for constraint and index names being pulled into your schema as `map` arguments on their respective attributes. 1. Example schema: ```prisma model User { id Int @id @default(autoincrement()) name String @unique posts Post[] } model Post { id Int @id @default(autoincrement()) title String authorName String @default("Anonymous") author User? @relation(fields: [authorName], references: [name]) } ``` 1. Introspect your **development database** to populate the Prisma schema with constraint and index names in your underlying database _that do not match Prisma ORM's naming convention_: ```terminal npx prisma db pull ``` In this example, the highlighted constraints did not conform to Prisma ORM's default naming convention and now include the `map` attribute field: ```prisma highlight=11;normal model User { id Int @id(map: "Custom_Constraint_Name") @default(autoincrement()) name String @unique posts Post[] } model Post { id Int @id @default(autoincrement()) title String authorName String @default("Anonymous") //highlight-next-line author User? @relation(fields: [authorName], references: [name], map: "Custom_Foreign_Key_Constraint") } ``` ## Option 2: I want to use Prisma ORM's default constraint and index names If you want to keep your Prisma Schema clean and if you have no reasons preventing you from renaming constraints and indexes in your database, then you can create a migration to update the names. Run `prisma migrate dev` to create a migration updating the constraint names to Prisma ORM's defaults. Afterwards, do not forget to `prisma migrate deploy` against your production environment if you have one to also update the names there. The schema below has no explicit constraint or index names spelled out, so Prisma ORM will infer them. 1. Example schema: ```prisma model User { name String @id //inferred as User_pkey posts Post[] } model Post { id Int @id @default(autoincrement()) //inferred as Post_pkey authorName String @default("Anonymous") author User? @relation(fields: [authorName], references: [name]) //inferred as Post_authorName_fkey } ``` 1. Run the `prisma migrate dev` command to generate a new migration: ```terminal npx prisma migrate dev ``` This migration renames any constraints that do not currently follow Prisma ORM's naming convention. 1. Run the [`prisma migrate deploy`](/orm/prisma-client/deployment/deploy-database-changes-with-prisma-migrate) command to apply the migration to your production environment: ```terminal npx prisma migrate deploy ``` ## Dealing with cases where more than one database environment is used for the same application ### Checking whether your environments use identical names Since Prisma ORM did not offer a way to define constraint or index names explicitly in the past, you can face situations where your different database environments have differing constraint or index names. In order to detect this: - Create a backup of your current `schema.prisma` file. - Run `prisma db pull` against each database environment, by saving the results to their own separate files using the `--schema` option. [See reference](/orm/reference/prisma-cli-reference#arguments-1) Then you can either manually inspect both files or use a `diff` tool in your IDE or in the terminal. If you see differences in constraint names, your production and local environments are out of sync and should be aligned. In the following example, the `Post` model has a foreign key constraint with a custom name in production that does not match development. #### Development environment: ```prisma highlight=5;normal model Post { id Int @id @default(autoincrement()) title String authorName String @default("Anonymous") //highlight-next-line author User? @relation(fields: [authorName], references: [name], map: "Custom_Foreign_Key_Constraint") } ``` #### Production environment: ```prisma highlight=5;normal model Post { id Int @id @default(autoincrement()) title String authorName String @default("Anonymous") //highlight-next-line author User? @relation(fields: [authorName], references: [name], map: "Custom_Production_Name") } ``` ### Aligning your environments if their constraint or index names differ If the names in your environments differ, the safest option is to align your development environment with the names in your production environment. This makes sure that no changes need to be performed on your production database. In order to achieve this: - Run `prisma db pull` against your production environment to pull in the constraint and index names - Switch to development and run `prisma migrate dev` to create a new migration. You can call that migration `migration-to-sync-names` - Switch to production, and run `prisma migrate resolve --applied migration-to-sync-names` to mark the migration as applied on production Your migration history now contains a migration to ensure that the names of any new environments you spin up contain the same names as your production database. And Prisma ORM knows not to apply this migration to production since you already marked it as applied. Your environments are now in sync and you can proceed to the [upgrade paths for migrate users](#option-2-i-want-to-use-prisma-orms-default-constraint-and-index-names). These let you choose your future naming scheme. --- # Referential actions upgrade path URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/referential-actions Prisma ORM version 2.x prevents deletion of connected records in some Prisma Client functions, and does not let you configure referential actions in your Prisma Schema to change that behavior. Prisma ORM version 3.x and later lets you control what should happen when deleting or updating records by explicitly setting referential actions on your models' relations. After the upgrade, Prisma Client will not enforce any referential actions anymore, and any action written to the database foreign keys will define the behavior when deleting or updating records. Prisma Migrate 3.x will use the actions previously done by Prisma Client as the new default when writing the foreign key constraints to the database. ## Prisma ORM 2.x behavior When invoking the [`delete()`](/orm/prisma-client/queries/crud#delete-a-single-record) or [`deleteAll()`](/orm/prisma-client/queries/crud#delete-all-records) methods using Prisma Client on required relations, a runtime check is performed and the deletion of records prevented if they are referencing related objects. **This prevents cascade behavior, no matter how the foreign key is defined**. The behavior in Prisma ORM 2, without upgrading, does not allow setting referential actions at all. [See Prisma ORM 2.x default referential actions](#prisma-orm-2x-default-referential-actions) If you need to actually use the cascade behavior configured in the database, you _can_ use [`raw`](/orm/prisma-client/using-raw-sql/raw-queries) SQL queries to [delete multiple referenced records](/orm/prisma-client/queries/crud#deleting-all-data-with-raw-sql--truncate). This is because Prisma Client will **not** perform runtime checks on raw queries. ### Prisma ORM 2.x default referential actions Below are the default referential actions written to the database foreign keys when using Prisma Migrate versions 2.x: | Clause | Optional relations | Mandatory relations | | :--------- | :----------------- | :------------------ | | `onDelete` | `SetNull` | `Cascade` | | `onUpdate` | `Cascade` | `Cascade` | On top of the database referential actions, the following actions are enforced in Prisma Client versions 2.x: | Clause | Optional relations | Mandatory relations | | :--------- | :----------------- | :------------------ | | `onDelete` | `SetNull` | `Restrict` | | `onUpdate` | `Cascade` | `Cascade` | ## Upgrade paths There are a couple of paths you can take when upgrading which will give different results depending on the desired outcome. If you currently use the migration workflow, you can run `prisma db pull` to check how the defaults are reflected in your schema. You can then manually update your database if you need to. You can also decide to skip checking the defaults and run a migration to update your database with the new default values. ### Using Introspection If you [Introspect](/orm/prisma-schema/introspection) your database, the referential actions configured at the database level will be reflected in your Prisma Schema. If you have been using Prisma Migrate or `prisma db push` to manage the database schema, these are likely to be the [\<=2.25.0 default values](#prisma-orm-2x-default-referential-actions). When you run an Introspection, Prisma ORM compares all the foreign keys in the database with the schema, if the SQL statements `ON DELETE` and `ON UPDATE` do **not** match the default values, they will be explicitly set in the schema file. After introspecting, you can review the non-default clauses in your schema. The most important clause to review is `onDelete`, which defaults to `Cascade` in version 2.25.0 and earlier. If you are using either the [`delete()`](/orm/prisma-client/queries/crud#delete-a-single-record) or [`deleteAll()`](/orm/prisma-client/queries/crud#delete-all-records) methods, **cascading deletes will now be performed, as the safety net in Prisma Client that previously prevented cascading deletes at runtime is removed**. Be sure to check your code and make any adjustments accordingly. Make sure you are happy with every case of `onDelete: Cascade` in your schema. If not, either: - Modify your Prisma schema and `db push` or `dev migrate` to change the database _or_ - Manually update the underlying database if you only use `prisma db pull` in your workflow The following example would result in a cascading delete, meaning that if the `User` is deleted then all of their `Post`'s will be deleted too. #### A blog schema example ```prisma highlight=4;add model Post { id Int @id @default(autoincrement()) title String //add-next-line author User @relation(fields: [authorId], references: [id], onDelete: Cascade) authorId Int } model User { id Int @id @default(autoincrement()) posts Post[] } ``` ### Using Migration When running a [Migration](/orm/prisma-migrate) (or the [`prisma db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) command) the [new defaults](/orm/prisma-schema/data-model/relations/referential-actions#referential-action-defaults) will be applied to your database. Unlike when you run `prisma db pull` for the first time, the new referential actions clause and property will **not** automatically be added to your Prisma schema by the Prisma VSCode extension. You will have to manually add them if you wish to use anything other than the new defaults. Explicitly defining referential actions in your Prisma schema is optional. If you do not explicitly define a referential action for a relation, Prisma ORM uses the [new defaults](/orm/prisma-schema/data-model/relations/referential-actions#referential-action-defaults). Note that referential actions can be added on a case by case basis. This means that you can add them to one single relation and leave the rest set to the defaults by not manually specifying anything. ### Checking for errors **Before** upgrading to version 3.0.1 (or versions 2.26.0 and above with the `referentialActions` feature flag enabled), Prisma ORM prevented the deletion of records while using `delete()` or `deleteMany()` to preserve referential integrity. A custom runtime error would be thrown by Prisma Client with the error code `P2014`. **After** upgrading, Prisma ORM no longer performs runtime checks. You can instead specify a custom referential action to preserve the referential integrity between relations. When you use [`NoAction`](/orm/prisma-schema/data-model/relations/referential-actions#noaction) or [`Restrict`](/orm/prisma-schema/data-model/relations/referential-actions#restrict) to prevent the deletion of records, the error messages will be different in versions 3.0.1 and above (or 2.26.0 with the `referentialActions` feature flag enabled) compared to versions prior to that. This is because they are now triggered by the database and **not** Prisma Client. The new error code that can be expected is `P2003`, so you should check your code to make adjustments accordingly. #### Example of catching errors The following example uses the below blog schema with a 1-m relationship between `Post` and `User` and sets a [`Restrict`](/orm/prisma-schema/data-model/relations/referential-actions#restrict) referential actions on the `author` field. This means that if a user has a post, that user (and their posts) **cannot** be deleted. ```prisma file=schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) title String author User @relation(fields: [authorId], references: [id], onDelete: Restrict) authorId String } model User { id Int @id @default(autoincrement()) posts Post[] } ``` Prior to upgrading, the error code you would receive when trying to delete a user which has posts would be `P2014` and it's message: > "The change you are trying to make would violate the required relation '\{relation_name}' between the \{model_a_name} and \{model_b_name} models." ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { try { await prisma.user.delete({ where: { id: 'some-long-id', }, }) } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { if (error.code === 'P2014') { console.log(error.message) } } } } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` To make sure you are checking for the correct errors in your code, modify your check to look for `P2003`, which will deliver the message: > "Foreign key constraint failed on the field: \{field_name}" ```ts highlight=14;delete|15;add import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { try { await prisma.user.delete({ where: { id: 'some-long-id' } }) } catch (error) { if (error instanceof Prisma.PrismaClientKnownRequestError) { //delete-next-line if (error.code === 'P2014') { //add-next-line if (error.code === 'P2003') { console.log(error.message) } } } } main() .then(async () => { await prisma.$disconnect() }) .catch(async (e) => { console.error(e) await prisma.$disconnect() process.exit(1) }) ``` --- # Upgrade to Prisma ORM 3 URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/index Prisma ORM 3 introduces a number of **breaking changes** if you are upgrading from an earlier version (any 2.x version), therefore, it is important to understand how this upgrade might affect your application and make any needed adjustments to ensure a smooth transition. Below you will find a list of the breaking changes and how to handle them. ## Breaking changes ### [Referential actions](/orm/prisma-schema/data-model/relations/referential-actions) The introduction of referential actions in version 3.x removes the safety net in Prisma Client that had previously prevented cascading deletes at runtime. As a result, depending on which workflow you are using to work on your application, you could be impacted. We advise you to check your schema and decide if you need to define referential actions explicitly. See [Referential action upgrade path](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/referential-actions) to understand how to proceed. ### [Named constraints](/orm/prisma-schema/data-model/database-mapping) We changed the convention followed by Prisma ORM to name constraints and indexes. We also introduced a clear distinction between the `map` attribute (database-level name) and `name` attribute (Prisma Client API name) in the PSL to explicitly control how constraints are defined in the Prisma schema. This means that you will notice an impact when running Prisma `migrate` or `db pull` which will follow this new convention. We advise you to adjust your schema to reflect the names of your constraints and indexes appropriately. You can check out the [Named constraints upgrade path](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3/named-constraints) for more information on how to proceed. ### [$queryRaw](/orm/prisma-client/using-raw-sql/raw-queries) From version 3.x onwards, the `$queryRaw` method now only supports a template literal. This means that if your application relied on `$queryRaw` calls using _strings_, those calls will **not** work anymore. We advise you to use template literals wherever possible for security reasons or resort to `$queryRawUnsafe` otherwise, after carefully escaping queries to prevent SQL injections. You can learn more about the new `$queryRaw` and `$queryRawUnsafe` methods in the [Raw database access](/orm/prisma-client/using-raw-sql/raw-queries) section of the docs. ### [Json Null Equality](/orm/prisma-client/special-fields-and-types/working-with-json-fields#filtering-by-null-values) You cannot filter a `Json` field by a null value. [See this GitHub issue](https://github.com/prisma/prisma/issues/8399). This is because `{ equals: null }` checks if the column value in the database is `NULL`, not if the JSON value inside the column equals `null`. To fix this problem, we decided to split null on Json fields into `JsonNull`, `DbNull` and `AnyNull`. - **JsonNull**: Selects the null value in JSON. - **DbNull**: Selects the NULL value in the database. - **AnyNull:** Selects both null JSON values and NULL database values. Given the following model in your Prisma Schema: ```ts model Log { id Int @id meta Json } ``` Starting in 3.0.1, you'll see a TypeError if you try to filter by null on a `Json` field: ```ts prisma.log.findMany({ where: { data: { meta: { equals: null ^ TypeError: Type 'null' is not assignable to type } }, }, }); ``` To fix this, you'll import and use one of the new null types: ```ts highlight=7;normal import { Prisma } from '@prisma/client' prisma.log.findMany({ where: { data: { meta: { equals: Prisma.AnyNull, }, }, }, }) ``` This also applies to `create`, `update` and `upsert`. To insert a `null` value into a `Json` field, you would write: ```ts highlight=5;normal import { Prisma } from '@prisma/client' prisma.log.create({ data: { meta: Prisma.JsonNull, }, }) ``` And to insert a database `NULL` into a Json field, you would write: ```ts highlight=5;normal import { Prisma } from '@prisma/client' prisma.log.create({ data: { meta: Prisma.DbNull, }, }) ``` This API change does not apply to the MongoDB connector where there is not a difference between a JSON null and a database NULL. They also do not apply to the `array_contains` operator because there can only be a JSON null within an JSON array. Since there cannot be a database NULL within a JSON array, `{ array_contains: null }` is not ambiguous. ## Specific upgrade paths ## Upgrading the `prisma` and `@prisma/client` packages to Prisma ORM 3 To upgrade from version 2.x to 3.x, you need to update both the `prisma` and `@prisma/client` packages. Both the `prisma` and `@prisma/client` packages install with a caret `^` in their version number to safe guard against breaking changes. To ignore the caret `^` and upgrade across major versions, you can use the `@3` tag when upgrading with `npm`, or `yarn` . Before upgrading, check each **breaking change** to see how the upgrade might affect your application. ```terminal npm install prisma@3 @prisma/client@3 ``` ```terminal yarn up prisma@3 @prisma/client@3 ``` --- # Codemods URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/codemods The `@prisma/codemods` package helps you to upgrade your codebase as Prisma ORM evolves. You can checkout the repository, here: https://github.com/prisma/codemods ## Usage ```terminal $ npx @prisma/codemods <...options> ``` - `` - See [Transforms](#transforms) for available choices - `` - The directory of your app. i.e ./my-awesome-project ## Options - `(-f)orce` - Bypass Git safety checks and forcibly run codemods - `(-s)chemaPath` - Specify a path to your ./prisma/schema.prisma - `(-d)ry` - Dry run (no changes are made to files) - `(-p)rint` - Print transformed files to your terminal - `--instanceNames=myClient` - Useful when importing an already instantiated client (i.e import myClient from './myClient') ## Transforms | `` | Description | Example | | ------------- | ----------------------------------------------------------- | ----------------------------------------------- | | `namespace` | Codemod for `@prisma/client` namespace change | `npx @prisma/codemods namespace ./my-project` | | `findUnique` | Converts `prisma.x.findOne` to `prisma.x.findUnique` | `npx @prisma/codemods findUnique ./my-project` | | `to$` | to\$: Converts deprecated `prisma.x` methods to `prisma.$x` | `npx @prisma/codemods to$ ./my-project` | | `update-2.12` | Includes `namespace`/`findUnique`/`to$` | `npx @prisma/codemods update-2.12 ./my-project` | --- # Upgrading versions URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-versions/index To upgrade to the latest version of Prisma ORM: 1. Review [release notes](https://github.com/prisma/prisma/releases) on GitHub for breaking changes and new features. 1. Upgrade **both** of the following packages to the same version: - [`prisma`](https://www.npmjs.com/package/prisma) - [`@prisma/client`](https://www.npmjs.com/package/@prisma/client) 1. Upgrade your codebase where applicable. Breaking changes may require you to change your Prisma schema or the way you use Prisma Client. :::tip [codemods](/orm/more/upgrade-guides/upgrading-versions/codemods) help you refactor your code to account for breaking changes - for example, the 2.12.0 codemod automatically renames `findOne` to `findUnique`. ::: ## Common upgrade paths ### Prisma ORM 2 and onwards - [Upgrade to Prisma ORM 6](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6) - [Upgrade to Prisma ORM 5](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-5) - [Upgrade to Prisma ORM 4](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-4) - [Upgrade to Prisma ORM 3](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-3) ### Prisma 1 - [Upgrade from Prisma 1](/orm/more/upgrade-guides/upgrade-from-prisma-1) ## Testing new features, without upgrading ### `dev` distribution tag The `dev` [npm distribution tag](https://docs.npmjs.com/adding-dist-tags-to-packages/) points to the most recent development version of the package, which is published for each commit to the main branch of `prisma/prisma`. You can use the `dev` distribution tag to verify a fix or test a feature before it is officially released. To install the latest `dev` distribution tag: ```terminal npm install @prisma/client@dev prisma@dev ``` Do not use the `dev` distribution tag in production - wait until the official release that contains the features and fixes you are interested in is released. For example, fixes present `@prisma/client@2.23.0-dev.25` will eventually be released as part of `@prisma/client@2.23.0`. --- # Upgrading to use Preview features URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrading-to-use-preview-features Preview features are new features that can only be used by opting in using a corresponding feature flag. ## Enabling preview features Some releases include Preview features that are not considered production-ready, and must be enabled before you can use them. For more information about enabling Preview features, refer to the following documentation: - [Enable Prisma Client and schema preview features](/orm/reference/preview-features/client-preview-features) - [Enable Prisma CLI preview features](/orm/reference/preview-features/cli-preview-features) We do not recommend using Preview features in production. --- # How to upgrade URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade ## Overview This page helps you make an informed decision on when and how to upgrade from Prisma 1 to Prisma ORM version 2._x_ and later. ## Upgrade documentation The upgrade documentation consists of several pages, here's an overview of how to use them: - **How to upgrade** (_you are here_): Starting point to learn about the upgrade process in general. - [Schema incompatibilities](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql): A _reference_ page about the schema incompatibilities between Prisma 1 and Prisma ORM 2._x_ (and later versions). Reading this page is optional but it will give you a better understanding of certain steps in the upgrade process. In addition to these two pages, there are various _practical guides_ that walk you through an example scenario of the upgrade process: - [Upgrading the Prisma layer](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-the-prisma-layer-postgresql): No matter what your Prisma 1 setup looks like, you should **always start your upgrade process by following this guide**. Once you're done with that guide, you can choose **one of the following four guides to upgrade your application layer**: - [Old to new Nexus](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-nexus-prisma-to-nexus): Choose this guide if you're currently running Prisma 1 with GraphQL Nexus. - [prisma-binding to Nexus](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-prisma-binding-to-nexus): Choose this guide if you're currently running Prisma 1 with `prisma-binding` and want to upgrade to [Nexus](https://nexusjs.org/). - [prisma-binding to SDL-first](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-prisma-binding-to-sdl-first): Choose this guide if you're currently running Prisma 1 with `prisma-binding` and want to upgrade to an [SDL-first](https://www.prisma.io/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3) GraphQL server. - [REST API](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-a-rest-api): Choose this guide if you're currently running Prisma 1 using Prisma Client 1 and are building a REST API. ## Main differences between Prisma 1 and Prisma ORM version 2._x_ and later On a high-level, the biggest differences between Prisma 1 and Prisma ORM versions 2._x_ and later are summarized below. Prisma ORM 2._x_ and later versions: - don't require hosting a database proxy server (i.e., the [Prisma server](https://v1.prisma.io/docs/1.34/prisma-server/)). - make the features of Prisma 1 more modular and splits them into dedicated tools: - Prisma Client: An improved version of Prisma Client 1.0 - Prisma Migrate: Data modeling and migrations (formerly `prisma deploy`). - use the [Prisma schema](/orm/prisma-schema), a merge of Prisma 1 datamodel and `prisma.yml`. - use its own [modeling language](https://github.com/prisma/specs/tree/master/schema) instead of being based on GraphQL SDL. - don't expose ["a GraphQL API for your database"](https://www.prisma.io/blog/prisma-and-graphql-mfl5y2r7t49c) anymore, but only allows for _programmatic access_ via the Prisma Client API. - don't support Prisma ORM binding any more. - allows connecting Prisma ORM 2._x_ and later version to any existing database, via more powerful introspection ## Feature parity Prisma ORM 2._x_ and later versions do not yet have full feature parity with Prisma 1. The biggest feature that is still missing from Prisma ORM versions 2._x_ and later is real-time subscriptions. - **Real-time API (Subscriptions)**: Prisma ORM version 2._x_ and later currently [doesn't have a way to subscribe to events happening in the database](https://github.com/prisma/prisma/issues/298) and get notified in real time. It is currently unclear if, when, and in what form a real-time API will be added to Prisma ORM versions 2._x_ and later. For the time being, you can implement real-time functionality using native database triggers, or if you're using GraphQL subscriptions you can consider triggering subscriptions manually inside your _mutation resolvers_. ## Schema incompatibilities The database schema that is created when running `prisma deploy` in Prisma 1 is only partially compatible with the one that Prisma ORM versions 2._x_ and later creates. This section gives a quick overview of the general incompatibilities and the potential workarounds. - > **Note**: For a detailed explanation of the problems and respective workarounds, please refer to the [Schema incompatibilities](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql) page. Here's an overview of the different columns: - **Problem**: A short description of the problem when upgrading from Prisma 1 to Prisma ORM versions 2._x_ and later - **SQL**: Can this be solved by making a non-breaking change to the SQL schema? - **Prisma schema**: Can this be solved by making a non-breaking change to the schema in Prisma ORM versions 2._x_ and later? - **Breaking Prisma 1**: Do the SQL statements break the Prisma 1 setup? This is only relevant when you're choosing the gradual side-by-side [upgrade strategy](#upgrade-strategies). | Problem | SQL | Prisma schema | Breaking Prisma 1 | | ------------------------------------------------------------------------ | ------- | ------------- | ---------------------------------- | | Default values aren't represented in database | Yes | Yes | No | | Generated CUIDs as ID values aren't represented in database | No | Yes | No | | `@createdAt` isn't represented in database | Yes | Yes | No | | `@updatedAt` isn't represented in database | No | Yes | No | | Inline 1-1 relations are recognized as 1-n (missing `UNIQUE` constraint) | Yes | No | No | | _All_ non-inline relations are recognized as m-n | Yes | No | Yes | | Json type is represented as `TEXT` in database | Yes | No | No (MySQL)
Yes (PostgreSQL) | | Enums are represented as `TEXT` in database | Yes | No | No (MySQL)
Yes (PostgreSQL) | | Required 1-1 relations are not represented in database | No | Yes | No | | `@db` attributes from Prisma 1 are not transferred to the Prisma schema | No | Yes | No | | Mismatching CUID length | Yes | No | No | | Scalar lists (arrays) are maintained with extra table | Depends | No | Depends | > **Note**: A general drawback with the workarounds in the Prisma schema is that [changes to the Prisma schema get lost after re-introspecting the database](https://github.com/prisma/prisma/issues/2425) and need to be re-added manually after each introspection run. ## Prisma 1 Upgrade CLI The [Prisma 1 Upgrade CLI](https://github.com/prisma/prisma1-upgrade) helps you apply the workarounds that are explained on the [Schema incompatibilities](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql) page. It generates the SQL statements to fix the database schema and make it compatible with Prisma ORM versions 2._x_ and later. Note that you are in full control over the operations that are executed against your database, the Upgrade CLI only generates and prints the statements for you. The Upgrade CLI also takes care of the workarounds in the Prisma schema. On a high-level, the upgrade workflow using the Upgrade CLI looks as follows. For the **initial setup**: 1. You set up Prisma ORM by installing the Prisma ORM versions 2._x_ and later CLI and running `npx prisma init`. 1. You connect to your database and introspect it with `npx prisma db pull`. ![Prisma CLI introspection flow](./images/prisma-cli-introspection-flow.png) For **fixing the schema incompatibilities**: 1. You invoke the Upgrade CLI with `npx prisma-upgrade`. 1. The Upgrade CLI generates SQL commands for you to run on your database. 1. You run the SQL commands against your database. 1. You run the `prisma db pull` command again. 1. You run the `npx prisma-upgrade` command again. 1. The Upgrade CLI adjusts the Prisma schema (version 2._x_ and later) by adding missing attributes. ![Fixing the schema incompatibilities](./images/fix-schema-incompatibilities.png) Note that the Upgrade CLI is designed in a way that **you can stop and re-start the process at any time**. Once you ran a SQL command that was generated by the Upgrade CLI against your database, the SQL command will not show up the next time you invoke the Upgrade CLI. That way, you can gradually resolve all schema incompatibilities when it's convenient for you. ## Upgrade strategies There are two main upgrade strategies: - **Upgrade all at once**: Entirely remove Prisma 1 from your project and move everything over to Prisma ORM version 2._x_ or later at once. - **Gradual upgrade side-by-side**: Add Prisma ORM version 2._x_ and later to the existing Prisma 1 project and gradually replace existing Prisma 1 features with the newer Prisma features while running them side-by-side. Note that if you are planning to run Prisma 1 and Prisma ORM 2._x_ or later version side-by-side, you must not yet resolve the [schema compatibilities](#schema-incompatibilities) that are breaking the Prisma 1 setup. ### When to choose which strategy If your project is not yet running in production or has little traffic and user data, the **all at once** strategy is recommended. In case your project already sees a lot of traffic and has a lot of user data stored in the database, you might want to consider the **gradual** upgrade strategy where you're running Prisma 1 and Prisma ORM 2 or later side-by-side for a certain amount of time until you've replace all former Prisma 1 functionality with Prisma ORM 2 or later version. Note that you won't be able to fix the [schema incompatibilities](#schema-incompatibilities) that require a "Breaking Prisma 1" change if you choose the gradual upgrade strategy and intend to run Prisma 1 and Prisma ORM version 2._x_ or later side-by-side. That's because these data migrations are breaking the schema that Prisma 1 expects. This means that your Prisma Client API might not feel as idiomatic as it could, but you still get the full feature set of Prisma Client. ### Upgrade path No matter which of the strategies you choose, on a high-level the envisioned upgrade path looks as follows: 1. Install the new Prisma ORM version 2._x_ or later CLI as a development dependency 1. Create your Prisma schema and configure the database connection URL 1. Use the Prisma ORM version 2._x_ or later CLI to introspect your Prisma 1 database and generate your Prisma schema 1. Run the [Prisma 1 Upgrade CLI](https://github.com/prisma/prisma1-upgrade) to "fix" the Prisma schema 1. Install and generate Prisma Client version 2._x_ or later 1. Adjust your application code, specifically replace the API calls from the Prisma Client 1.0 with those of Prisma Client version 2._x_ or later ## Next steps Once you've made the decision to upgrade, continue with the [Upgrading the Prisma ORM layer](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-the-prisma-layer-postgresql) guide. --- # Schema incompatibilities URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-mysql ## Overview Each section on this page describes a potential problem when upgrading from Prisma 1 to Prisma ORM 2._x_ and later and explains the available workarounds. ## Default values aren't represented in database ### Problem When adding the `@default` directive in a Prisma 1 datamodel, the default values for this field are generated by the Prisma 1 server at runtime. There's no `DEFAULT` constraint added to the database column. Because this constraint is not reflected in the database itself, the Prisma ORM 2._x_ and later versions of introspection can't recognize it. ### Example #### Prisma 1 datamodel ```graphql type Post { id: ID! @id published: Boolean @default(value: false) } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "Post" ( id VARCHAR(25) PRIMARY KEY NOT NULL, published BOOLEAN NOT NULL ); ``` #### Result of introspection in Prisma ORM versions 2._x_ and later ```prisma file=schema.prisma showLineNumbers model Post { id String @id published Boolean } ``` Because the `DEFAULT` constraint has not been added to the database when mapping the Prisma 1 datamodel to the database with `prisma deploy`, Prisma ORM v2 (and later versions) doesn't recognize it during introspection. ### Workarounds #### Manually add a `DEFAULT` constraint to the database column You can alter the column to add the `DEFAULT` constraint as follows: ```sql ALTER TABLE `Post` ALTER COLUMN published SET DEFAULT false; ``` After this adjustment, you can re-introspect your database and the `@default` attribute will be added to the `published` field: ```prisma line-number file=schema.prisma highlight=3;normal showLineNumbers model Post { id String @id //highlight-next-line published Boolean @default(false) } ``` #### Manually add a `@default` attribute to the Prisma model You can add the `@default` attribute to the Prisma model: ```prisma line-number file=schema.prisma highlight=3;add showLineNumbers model Post { id String //add-next-line published Boolean @default(false) } ``` If the `@default` attribute is set in the Prisma schema and you run `prisma generate`, the resulting Prisma Client code will generate the specified default values at runtime (similar to what the Prisma 1 server did in Prisma 1). ## Generated CUIDs as ID values aren't represented in database ### Problem Prisma 1 auto-generates ID values as CUIDs for `ID` fields when they're annotated with the `@id` directive. These CUIDs are generated by the Prisma 1 server at runtime. Because this behavior is not reflected in the database itself, the introspection in Prisma ORM 2._x_ and later can't recognize it. ### Example #### Prisma 1 datamodel ```graphql type Post { id: ID! @id } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "Post" ( id VARCHAR(25) PRIMARY KEY NOT NULL ); ``` #### Result of introspection in Prisma ORM versions 2._x_ and later ```prisma file=schema.prisma showLineNumbers model Post { id String @id } ``` Because there's no indication of the CUID behavior in the database, Prisma ORM's introspection doesn't recognize it. ### Workaround As a workaround, you can manually add the `@default(cuid())` attribute to the Prisma model: ```prisma line-number file=schema.prisma highlight=2;add showLineNumbers model Post { //add-next-line id String @id @default(cuid()) } ``` If the `@default` attribute is set in the Prisma schema and you run `prisma generate`, the resulting Prisma Client code will generate the specified default values at runtime (similar to what the Prisma 1 server did in Prisma 1). Note that you'll have to re-add the attribute after each introspection because introspection removes it (as the previous version of the Prisma schema is overwritten)! ## `@createdAt` isn't represented in database ### Problem Prisma 1 auto-generates values for `DateTime` fields when they're annotated with the `@createdAt` directive. These values are generated by the Prisma 1 server at runtime. Because this behavior is not reflected in the database itself, the introspection in Prisma ORM 2._x_ and later can't recognize it. ### Example #### Prisma 1 datamodel ```graphql line-number highlight=3;normal type Post { id: ID! @id createdAt: DateTime! @createdAt } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "Post" ( id VARCHAR(25) PRIMARY KEY NOT NULL, "createdAt" TIMESTAMP NOT NULL ); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model Post { id String @id createdAt DateTime } ``` ### Workarounds #### Manually add `DEFAULT CURRENT_TIMESTAMP` to the database column You can alter the column to add the `DEFAULT` constraint as follows: ```sql ALTER TABLE "Post" ALTER COLUMN "createdAt" SET DEFAULT CURRENT_TIMESTAMP; ``` After this adjustment, you can re-introspect your database and the `@default` attribute will be added to the `createdAt` field: ```prisma file=schema.prisma showLineNumbers model Post { id String createdAt DateTime @default(now()) } ``` #### Manually add the `@default(now())` attribute to the Prisma model As a workaround, you can manually add the `@default(now())` attribute to the Prisma model: ```prisma line-number file=schema.prisma highlight=3;normal showLineNumbers model Post { id String @id //highlight-next-line createdAt DateTime @default(now()) } ``` If the `@default` attribute is set in the Prisma schema and you run `prisma generate`, the resulting Prisma Client code will generate the specified default values at runtime (similar to what the Prisma 1 server did in Prisma 1). Note that you'll have to re-add the attribute after each introspection because introspection removes it (as the previous version of the Prisma schema is overwritten)! ## `@updatedAt` isn't represented in database ### Problem Prisma 1 auto-generates values for `DateTime` fields when they're annotated with the `@updatedAt` directive. These values are generated by the Prisma 1 server at runtime. Because this behavior is not reflected in the database itself, the introspection in Prisma ORM 2._x_ and later can't recognize it.. ### Example #### Prisma 1 datamodel ```graphql type Post { id: ID! @id updatedAt: DateTime! @updatedAt } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "Post" ( id VARCHAR(25) PRIMARY KEY NOT NULL, updatedAt TIMESTAMP ); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model Post { id String @id updatedAt DateTime } ``` ### Workarounds #### Manually add the `@updatedAt` attribute to the Prisma model As a workaround, you can manually add the `@updatedAt` attribute to the Prisma model: ```prisma line-number file=schema.prisma highlight=3;add showLineNumbers model Post { id String @id //add-next-line updatedAt DateTime @updatedAt } ``` If the `@updatedAt` attribute is set in the Prisma schema and you run `prisma generate`, the resulting Prisma Client code will automatically generate values for this column when an existing record is updated (similar to what the Prisma 1 server did in Prisma 1). Note that you'll have to re-add the attribute after each introspection because introspection removes it (as the previous version of the Prisma schema is overwritten)! ## Inline 1-1 relations are recognized as 1-n (missing `UNIQUE` constraint) ### Problem In the [datamodel v1.1](https://www.prisma.io/blog/datamodel-v11-lrzqy1f56c90) that was introduced in Prisma ORM v1.31, 1-1 relations can be declared as _inline_. In that case, the relation will not be maintained via a [relation table](/orm/prisma-schema/data-model/relations/many-to-many-relations#relation-tables) but via a single foreign key on one of the two tables involved. When this approach is used, Prisma ORM doesn't add a `UNIQUE` constraint to the foreign key column which means that after introspection in Prisma ORM version 2._x_ and later, this former 1-1 relation will be added as a 1-n relation to the Prisma schema. ### Example #### Prisma ORM datamodel v1.1 (available from Prisma ORM v1.31) ```graphql type User { id: ID! @id profile: Profile @relation(link: INLINE) } type Profile { id: ID! @id user: User } ``` Note that omitting the `@relation` directive in this case would result in the same behavior because `link: INLINE` is the _default_ for 1-1 relations. #### Prisma 1 generated SQL migration ```sql CREATE TABLE "User" ( id VARCHAR(25) PRIMARY KEY NOT NULL ); CREATE TABLE "Profile" ( id VARCHAR(25) PRIMARY KEY NOT NULL, "user" VARCHAR(25), FOREIGN KEY ("user") REFERENCES "User"(id) ); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model User { id String @id Profile Profile[] } model Profile { id String @id user String? User User? @relation(fields: [user], references: [id]) } ``` Because there's no `UNIQUE` constraint defined on the `user` column (which represents the foreign key in this relation), Prisma ORM's introspection recognizes the relation as 1-n. ### Workaround #### Manually add `UNIQUE` constraint to the foreign key column You can alter the foreign key column to add the `UNIQUE` constraint as follows: ```sql ALTER TABLE `Profile` ADD CONSTRAINT userId_unique UNIQUE (`user`); ``` After this adjustment, you can re-introspect your database and the 1-1 relation will be properly recognized: ```prisma line-number file=schema.prisma highlight=3;normal showLineNumbers model User { id String @id //highlight-next-line Profile Profile? } model Profile { id String @id user String? @unique User User? @relation(fields: [user], references: [id]) } ``` ## _All_ non-inline relations are recognized as m-n ### Problem Prisma 1 represents relations as relation tables most of the time: - All relations in the Prisma 1 **datamodel v1.0** are represented as relation tables - In **datamodel v1.1**, all m-n relations as well as the 1-1 and 1-n relations declared as `link: TABLE` are represented as relation tables. Because of this representation, introspection in Prisma ORM version 2._x_ and later will recognize all these relations as m-n relations, even though they might have been declared as 1-1 or 1-n in Prisma 1. ### Example #### Prisma 1 datamodel ```graphql type User { id: ID! @id posts: [Post!]! } type Post { id: ID! @id author: User! @relation(link: TABLE) } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "User" ( id VARCHAR(25) PRIMARY KEY NOT NULL ); CREATE TABLE "Post" ( id VARCHAR(25) PRIMARY KEY NOT NULL ); CREATE TABLE "_PostToUser" ( "A" VARCHAR(25) NOT NULL REFERENCES "Post"(id) ON DELETE CASCADE, "B" VARCHAR(25) NOT NULL REFERENCES "User"(id) ON DELETE CASCADE ); CREATE UNIQUE INDEX "_PostToUser_AB_unique" ON "_PostToUser"("A" text_ops,"B" text_ops); CREATE INDEX "_PostToUser_B" ON "_PostToUser"("B" text_ops); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model User { id String @id Post Post[] @relation(references: [id]) } model Post { id String @id User User[] @relation(references: [id]) } ``` Because the relation table that was created by Prisma 1 uses the same [conventions for relation tables](/orm/prisma-schema/data-model/relations/many-to-many-relations#conventions-for-relation-tables-in-implicit-m-n-relations) as in Prisma ORM version 2._x_ and later, the relation now gets recognized as a m-n relation. ### Workaround As a workaround, you can migrate the data into a structure that's compatible with Prisma ORM's 1-n relation: 1. Create new column `authorId` on the `Post` table. This column should be a _foreign key_ that references the `id` field of the `User` table: ```sql ALTER TABLE `Post` ADD COLUMN `authorId` VARCHAR(25); ALTER TABLE `Post` ADD FOREIGN KEY (`authorId`) REFERENCES `User` (`id`); ``` 1. Write a SQL query that reads all the rows from the `_PostToUser` relation table and for each row: 1. Finds the respective `Post` record by looking up the value from column `A` 1. Inserts the value from column `B` as the value for `authorId` into that `Post` record ```sql UPDATE Post, _PostToUser SET Post.authorId = _PostToUser.B WHERE Post.id = _PostToUser.A ``` 1. Delete the `_PostToUser` relation table ```sql DROP TABLE `_PostToUser`; ``` After that you can introspect your database and the relation will now be recognized as 1-n: ```prisma line-number file=schema.prisma highlight=3,8,9;normal showLineNumbers model User { id String @id //highlight-next-line Post Post[] } model Post { id String @id //highlight-start User User @relation(fields: [authorId], references: [id]) authorId String //highlight-end } ``` ## `Json` type is represented as `TEXT` in database ### Problem Prisma 1 supports the `Json` data type in its datamodel. However, in the underlying database, fields of type `Json` are actually stored as plain strings using the `TEXT` data type of the underlying database. Any parsing and validation of the stored JSON data is done by the Prisma 1 server at runtime. ### Example #### Prisma 1 datamodel ```graphql type User { id: ID! @id jsonData: Json } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "User" ( id VARCHAR(25) PRIMARY KEY NOT NULL, jsonData TEXT ); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model User { id String @id jsonData String? } ``` ### Workaround You can manually change the type of the column to `JSON` ```sql ALTER TABLE User MODIFY COLUMN jsonData JSON; ``` After this adjustment, you can re-introspect your database and the field will now be recognized as `Json`: ```prisma line-number file=schema.prisma highlight=3;normal showLineNumbers model User { id String @id //highlight-next-line jsonData Json? } ``` ## Enums are represented as `TEXT` in database ### Problem Prisma 1 supports the `enum` data type in its datamodel. However, in the underlying database, types declared as `enum` are actually stored as plain strings using the `TEXT` data type of the underlying database. Any validation of the stored `enum` data is done by the Prisma 1 server at runtime. ### Example #### Prisma 1 datamodel ```graphql type User { id: ID! @id role: Role } enum Role { ADMIN CUSTOMER } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "User" ( id VARCHAR(25) PRIMARY KEY NOT NULL, role TEXT ); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model User { id String @id role String? } ``` ### Workaround You can manually turn the `role` column into an enum with your desired values: 1. Create an `enum` in your database that mirrors the `enum` you defined in the Prisma 1 datamodel: ```sql CREATE TYPE "Role" AS ENUM ('CUSTOMER', 'ADMIN'); ``` 1. Change the type from `TEXT` to your new `enum`: ```sql ALTER TABLE "User" ALTER COLUMN "role" TYPE "Role" USING "role"::text::"Role"; ``` After introspection, the type is now properly recognized as an enum: ```prisma line-number file=schema.prisma highlight=3,6-9;normal showLineNumbers model User { id String @id //highlight-next-line role Role? } //highlight-start enum Role { ADMIN CUSTOMER } //highlight-end ``` ## Mismatching CUID length ### Problem Prisma 1 uses CUIDs as ID values for all database records. In the underlying database, these IDs are represented as strings with a maximum size of 25 characters (as `VARCHAR(25)`). However, when configuring default CUIDs in your Prisma ORM 2._x_ (or later versions) schema with `@default(cuid())` the generated ID values might exceed the limit of 25 characters (the maximum length might be 30 characters). To make your IDs proof for Prisma ORM 2._x_ (or later versions), you therefore need to adjust the column type to `VARCHAR(30)`. ### Example #### Prisma 1 datamodel ```graphql type User { id: ID! @id } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "User" ( id VARCHAR(25) PRIMARY KEY NOT NULL ); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model User { id String @id } ``` ### Workaround You can manually turn the `VARCHAR(25)` columns into `VARCHAR(30)`: ```sql SET FOREIGN_KEY_CHECKS=0; ALTER TABLE `User` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL; SET FOREIGN_KEY_CHECKS=1; ``` > **Note**: When fixing this issue with the [Upgrade CLI](/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade#prisma-1-upgrade-cli), the generated SQL statements will keep appearing in the Upgrade CLI even after you have changed the column types in the underlying database. This is a currently a limitation in the Upgrade CLI. ## Scalar lists (arrays) are maintained with extra table ### Problem In Prisma 1, you can define lists of _scalar_ types on your models. Under the hood, this is implemented with an extra table that keeps track of the values in the list. To remove the approach with the extra table which incurred hidden performance costs, Prisma ORM 2._x_ and later versions only support scalar lists only when they're natively supported by the database you use. At the moment, only [PostgreSQL supports scalar lists (arrays) natively](https://www.postgresql.org/docs/9.1/arrays.html). With PostgreSQL, you therefore can keep using scalar lists in Prisma ORM 2._x_ and later versions, but you'll need to perform a data migration to transfer the data from the extra table from Prisma 1 into an actual PostgreSQL array. ### Example #### Prisma 1 datamodel ```graphql type User { id: ID! @id coinflips: [Boolean!]! @scalarList(strategy: RELATION) } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "User" ( id VARCHAR(25) PRIMARY KEY NOT NULL ); CREATE TABLE "User_coinflips" ( "nodeId" VARCHAR(25) REFERENCES "User"(id), position INTEGER, value BOOLEAN NOT NULL, CONSTRAINT "User_coinflips_pkey" PRIMARY KEY ("nodeId", position) ); CREATE UNIQUE INDEX "User_coinflips_pkey" ON "User_coinflips"("nodeId" text_ops,position int4_ops); ``` #### Result of Prisma ORM 2 introspection ```prisma file=schema.prisma showLineNumbers model User { id String @id User_coinflips User_coinflips[] } model User_coinflips { nodeId String position Int value Boolean User User @relation(fields: [nodeId], references: [id]) @@id([nodeId, position]) } ``` Note that you can now generate Prisma Client and you'll be able to access the data from the scalar lists through the extra table. PostgreSQL users can alternatively migrate the data into a native PostgreSQL array and continue to benefit from the slicker Prisma Client API for scalar lists (read the section below for more info).
Expand for sample Prisma Client API calls To access the coinflips data, you will now have to always [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) it in your queries: ```ts const user = await prisma.user.findUnique({ where: { id: 1 }, include: { coinflips: { orderBy: { position: 'asc' }, }, }, }) ``` > **Note**: The `orderBy` is important to retain the order of the list. This is the `result of the query: ```js { id: 1, name: 'Alice', coinflips: [ { id: 1, position: 1000, value: false }, { id: 2, position: 2000, value: true }, { id: 3, position: 3000, value: false }, { id: 4, position: 4000, value: true }, { id: 5, position: 5000, value: true }, { id: 6, position: 6000, value: false } ] } ``` To access just the boolean values from the list, you can `map` over the `coinflips` on `user` as follows: ```ts const currentCoinflips = user!.coinflips.map((cf) => cf.value) ``` > **Note**: The exclamation mark above means that you're _force unwrapping_ the `user` value. This is necessary because the `user` returned from the previous query might be `null`. Here's the value of `currentCoinflips` after the call to `map`: ```json [false, true, false, true, true, false] ```
### Workaround The following workaround is only available for PostgreSQL users! As scalar lists (i.e. [arrays](https://www.postgresql.org/docs/9.1/arrays.html)) are available as a native PostgreSQL feature, you can keep using the same notation of `coinflips: Boolean[]` in your Prisma schema. However, in order to do so you need to manually migrate the underlying data from the `User_coinflips` table into a PostgreSQL array. Here's how you can do that: 1. Add the new `coinflips` column to the `User` tables: ```sql ALTER TABLE "User" ADD COLUMN coinflips BOOLEAN[]; ``` 1. Migrate the data from `"User_coinflips".value` to `"User.coinflips"`: ```sql UPDATE "User" SET coinflips = t.flips FROM ( SELECT "nodeId", array_agg(VALUE ORDER BY position) AS flips FROM "User_coinflips" GROUP BY "nodeId" ) t where t."nodeId" = "User"."id"; ``` 1. To cleanup, you can delete the `User_coinflips` table: ```sql DROP TABLE "User_coinflips"; ``` You can now introspect your database and the `coinflips` field will be represented as an array in your new Prisma schema: ```prisma file=schema.prisma showLineNumbers model User { id String @id coinflips Boolean[] } ``` You can keep using Prisma Client as before: ```ts const user = await prisma.user.findUnique({ where: { id: 1 }, }) ``` This is the result from the API call: ```js { id: 1, name: 'Alice', coinflips: [ false, true, false, true, true, false ] } ``` --- # Schema incompatibilities URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql ## Overview Each section on this page describes a potential problem when upgrading from Prisma 1 to Prisma ORM 2._x_ and later and explains the available workarounds. ## Default values aren't represented in database ### Problem When adding the `@default` directive in a Prisma 1 datamodel, the default values for this field are generated by the Prisma 1 server at runtime. There's no `DEFAULT` constraint added to the database column. Because this constraint is not reflected in the database itself, the Prisma ORM 2._x_ and later versions of introspection can't recognize it. ### Example #### Prisma 1 datamodel ```graphql type Post { id: ID! @id published: Boolean @default(value: false) } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "Post" ( id VARCHAR(25) PRIMARY KEY NOT NULL, published BOOLEAN NOT NULL ); ``` #### Result of introspection in Prisma ORM versions 2._x_ and later ```prisma file=schema.prisma showLineNumbers model Post { id String @id published Boolean } ``` Because the `DEFAULT` constraint has not been added to the database when mapping the Prisma 1 datamodel to the database with `prisma deploy`, Prisma ORM v2 (and later versions) doesn't recognize it during introspection. ### Workarounds #### Manually add a `DEFAULT` constraint to the database column You can alter the column to add the `DEFAULT` constraint as follows: ```sql ALTER TABLE "Post" ALTER COLUMN published SET DEFAULT false; ``` After this adjustment, you can re-introspect your database and the `@default` attribute will be added to the `published` field: ```prisma line-number file=schema.prisma highlight=3;normal showLineNumbers model Post { id String @id //highlight-next-line published Boolean @default(false) } ``` #### Manually add a `@default` attribute to the Prisma model You can add the `@default` attribute to the Prisma model: ```prisma line-number file=schema.prisma highlight=3;add showLineNumbers model Post { id String //add-next-line published Boolean @default(false) } ``` If the `@default` attribute is set in the Prisma schema and you run `prisma generate`, the resulting Prisma Client code will generate the specified default values at runtime (similar to what the Prisma 1 server did in Prisma 1). ## Generated CUIDs as ID values aren't represented in database ### Problem Prisma 1 auto-generates ID values as CUIDs for `ID` fields when they're annotated with the `@id` directive. These CUIDs are generated by the Prisma 1 server at runtime. Because this behavior is not reflected in the database itself, the introspection in Prisma ORM 2._x_ and later can't recognize it. ### Example #### Prisma 1 datamodel ```graphql type Post { id: ID! @id } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "Post" ( id VARCHAR(25) PRIMARY KEY NOT NULL ); ``` #### Result of introspection in Prisma ORM versions 2._x_ and later ```prisma file=schema.prisma showLineNumbers model Post { id String @id } ``` Because there's no indication of the CUID behavior in the database, Prisma ORM's introspection doesn't recognize it. ### Workaround As a workaround, you can manually add the `@default(cuid())` attribute to the Prisma model: ```prisma line-number file=schema.prisma highlight=2;add showLineNumbers model Post { //add-next-line id String @id @default(cuid()) } ``` If the `@default` attribute is set in the Prisma schema and you run `prisma generate`, the resulting Prisma Client code will generate the specified default values at runtime (similar to what the Prisma 1 server did in Prisma 1). Note that you'll have to re-add the attribute after each introspection because introspection removes it (as the previous version of the Prisma schema is overwritten)! ## `@createdAt` isn't represented in database ### Problem Prisma 1 auto-generates values for `DateTime` fields when they're annotated with the `@createdAt` directive. These values are generated by the Prisma 1 server at runtime. Because this behavior is not reflected in the database itself, the introspection in Prisma ORM 2._x_ and later can't recognize it. ### Example #### Prisma 1 datamodel ```graphql line-number highlight=3;normal type Post { id: ID! @id createdAt: DateTime! @createdAt } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "Post" ( id VARCHAR(25) PRIMARY KEY NOT NULL, "createdAt" TIMESTAMP NOT NULL ); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model Post { id String @id createdAt DateTime } ``` ### Workarounds #### Manually add `DEFAULT CURRENT_TIMESTAMP` to the database column You can alter the column to add the `DEFAULT` constraint as follows: ```sql ALTER TABLE "Post" ALTER COLUMN "createdAt" SET DEFAULT CURRENT_TIMESTAMP; ``` After this adjustment, you can re-introspect your database and the `@default` attribute will be added to the `createdAt` field: ```prisma file=schema.prisma showLineNumbers model Post { id String createdAt DateTime @default(now()) } ``` #### Manually add the `@default(now())` attribute to the Prisma model As a workaround, you can manually add the `@default(now())` attribute to the Prisma model: ```prisma line-number file=schema.prisma highlight=3;normal model Post { id String @id //highlight-next-line createdAt DateTime @default(now()) } ``` If the `@default` attribute is set in the Prisma schema and you run `prisma generate`, the resulting Prisma Client code will generate the specified default values at runtime (similar to what the Prisma 1 server did in Prisma 1). Note that you'll have to re-add the attribute after each introspection because introspection removes it (as the previous version of the Prisma schema is overwritten)! ## `@updatedAt` isn't represented in database ### Problem Prisma 1 auto-generates values for `DateTime` fields when they're annotated with the `@updatedAt` directive. These values are generated by the Prisma 1 server at runtime. Because this behavior is not reflected in the database itself, the introspection in Prisma ORM 2._x_ and later can't recognize it.. ### Example #### Prisma 1 datamodel ```graphql type Post { id: ID! @id updatedAt: DateTime! @updatedAt } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "Post" ( id VARCHAR(25) PRIMARY KEY NOT NULL, updatedAt TIMESTAMP ); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model Post { id String @id updatedAt DateTime } ``` ### Workarounds #### Manually add the `@updatedAt` attribute to the Prisma model As a workaround, you can manually add the `@updatedAt` attribute to the Prisma model: ```prisma line-number file=schema.prisma highlight=3;add model Post { id String @id //add-next-line updatedAt DateTime @updatedAt } ``` If the `@updatedAt` attribute is set in the Prisma schema and you run `prisma generate`, the resulting Prisma Client code will automatically generate values for this column when an existing record is updated (similar to what the Prisma 1 server did in Prisma 1). Note that you'll have to re-add the attribute after each introspection because introspection removes it (as the previous version of the Prisma schema is overwritten)! ## Inline 1-1 relations are recognized as 1-n (missing `UNIQUE` constraint) ### Problem In the [datamodel v1.1](https://www.prisma.io/blog/datamodel-v11-lrzqy1f56c90) that was introduced in Prisma ORM v1.31, 1-1 relations can be declared as _inline_. In that case, the relation will not be maintained via a [relation table](/orm/prisma-schema/data-model/relations/many-to-many-relations#relation-tables) but via a single foreign key on one of the two tables involved. When this approach is used, Prisma ORM doesn't add a `UNIQUE` constraint to the foreign key column which means that after introspection in Prisma ORM version 2._x_ and later, this former 1-1 relation will be added as a 1-n relation to the Prisma schema. ### Example #### Prisma ORM datamodel v1.1 (available from Prisma ORM v1.31) ```graphql type User { id: ID! @id profile: Profile @relation(link: INLINE) } type Profile { id: ID! @id user: User } ``` Note that omitting the `@relation` directive in this case would result in the same behavior because `link: INLINE` is the _default_ for 1-1 relations. #### Prisma 1 generated SQL migration ```sql CREATE TABLE "User" ( id VARCHAR(25) PRIMARY KEY NOT NULL ); CREATE TABLE "Profile" ( id VARCHAR(25) PRIMARY KEY NOT NULL, "user" VARCHAR(25), FOREIGN KEY ("user") REFERENCES "User"(id) ); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model User { id String @id Profile Profile[] } model Profile { id String @id user String? User User? @relation(fields: [user], references: [id]) } ``` Because there's no `UNIQUE` constraint defined on the `user` column (which represents the foreign key in this relation), Prisma ORM's introspection recognizes the relation as 1-n. ### Workaround #### Manually add `UNIQUE` constraint to the foreign key column You can alter the foreign key column to add the `UNIQUE` constraint as follows: ```sql ALTER TABLE "Profile" ADD CONSTRAINT userId_unique UNIQUE ("user"); ``` After this adjustment, you can re-introspect your database and the 1-1 relation will be properly recognized: ```prisma line-number file=schema.prisma highlight=3;normal model User { id String @id //highlight-next-line Profile Profile? } model Profile { id String @id user String? @unique User User? @relation(fields: [user], references: [id]) } ``` ## _All_ non-inline relations are recognized as m-n ### Problem Prisma 1 represents relations as relation tables most of the time: - All relations in the Prisma 1 **datamodel v1.0** are represented as relation tables - In **datamodel v1.1**, all m-n relations as well as the 1-1 and 1-n relations declared as `link: TABLE` are represented as relation tables. Because of this representation, introspection in Prisma ORM version 2._x_ and later will recognize all these relations as m-n relations, even though they might have been declared as 1-1 or 1-n in Prisma 1. ### Example #### Prisma 1 datamodel ```graphql type User { id: ID! @id posts: [Post!]! } type Post { id: ID! @id author: User! @relation(link: TABLE) } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "User" ( id VARCHAR(25) PRIMARY KEY NOT NULL ); CREATE TABLE "Post" ( id VARCHAR(25) PRIMARY KEY NOT NULL ); CREATE TABLE "_PostToUser" ( "A" VARCHAR(25) NOT NULL REFERENCES "Post"(id) ON DELETE CASCADE, "B" VARCHAR(25) NOT NULL REFERENCES "User"(id) ON DELETE CASCADE ); CREATE UNIQUE INDEX "_PostToUser_AB_unique" ON "_PostToUser"("A" text_ops,"B" text_ops); CREATE INDEX "_PostToUser_B" ON "_PostToUser"("B" text_ops); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model User { id String @id Post Post[] @relation(references: [id]) } model Post { id String @id User User[] @relation(references: [id]) } ``` Because the relation table that was created by Prisma 1 uses the same [conventions for relation tables](/orm/prisma-schema/data-model/relations/many-to-many-relations#conventions-for-relation-tables-in-implicit-m-n-relations) as in Prisma ORM version 2._x_ and later, the relation now gets recognized as a m-n relation. ### Workaround As a workaround, you can migrate the data into a structure that's compatible with Prisma ORM's 1-n relation: 1. Create new column `authorId` on the `Post` table. This column should be a _foreign key_ that references the `id` field of the `User` table: ```sql ALTER TABLE "Post" ADD COLUMN "authorId" VARCHAR(25); ALTER TABLE "Post" ADD CONSTRAINT fk_author FOREIGN KEY ("authorId") REFERENCES "User"("id"); ``` 1. Write a SQL query that reads all the rows from the `_PostToUser` relation table and for each row: 1. Finds the respective `Post` record by looking up the value from column `A` 1. Inserts the value from column `B` as the value for `authorId` into that `Post` record ```sql UPDATE "Post" post SET "authorId" = post_to_user."B" FROM "_PostToUser" post_to_user WHERE post_to_user."A" = post."id"; ``` 1. Delete the `_PostToUser` relation table ```sql DROP TABLE "_PostToUser"; ``` After that you can introspect your database and the relation will now be recognized as 1-n: ```prisma line-number file=schema.prisma highlight=3,8,9;normal model User { id String @id //highlight-next-line Post Post[] } model Post { id String @id //highlight-start User User @relation(fields: [authorId], references: [id]) authorId String //highlight-end } ``` ## `Json` type is represented as `TEXT` in database ### Problem Prisma 1 supports the `Json` data type in its datamodel. However, in the underlying database, fields of type `Json` are actually stored as plain strings using the `TEXT` data type of the underlying database. Any parsing and validation of the stored JSON data is done by the Prisma 1 server at runtime. ### Example #### Prisma 1 datamodel ```graphql type User { id: ID! @id jsonData: Json } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "User" ( id VARCHAR(25) PRIMARY KEY NOT NULL, jsonData TEXT ); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model User { id String @id jsonData String? } ``` ### Workaround You can manually change the type of the column to `JSON` ```sql ALTER TABLE "User" ALTER COLUMN "jsonData" TYPE JSON USING "jsonData"::json; ``` After this adjustment, you can re-introspect your database and the field will now be recognized as `Json`: ```prisma line-number file=schema.prisma highlight=3;normal showLineNumbers model User { id String @id //highlight-next-line jsonData Json? } ``` ## Enums are represented as `TEXT` in database ### Problem Prisma 1 supports the `enum` data type in its datamodel. However, in the underlying database, types declared as `enum` are actually stored as plain strings using the `TEXT` data type of the underlying database. Any validation of the stored `enum` data is done by the Prisma 1 server at runtime. ### Example #### Prisma 1 datamodel ```graphql type User { id: ID! @id role: Role } enum Role { ADMIN CUSTOMER } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "User" ( id VARCHAR(25) PRIMARY KEY NOT NULL, role TEXT ); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model User { id String @id role String? } ``` ### Workaround You can manually turn the `role` column into an enum with your desired values: 1. Create an `enum` in your database that mirrors the `enum` you defined in the Prisma 1 datamodel: ```sql CREATE TYPE "Role" AS ENUM ('CUSTOMER', 'ADMIN'); ``` 1. Change the type from `TEXT` to your new `enum`: ```sql ALTER TABLE "User" ALTER COLUMN "role" TYPE "Role" USING "role"::text::"Role"; ``` After introspection, the type is now properly recognized as an enum: ```prisma line-number file=schema.prisma highlight=3,6-9;normal showLineNumbers model User { id String @id //highlight-next-line role Role? } //highlight-start enum Role { ADMIN CUSTOMER } //highlight-end ``` ## Mismatching CUID length ### Problem Prisma 1 uses CUIDs as ID values for all database records. In the underlying database, these IDs are represented as strings with a maximum size of 25 characters (as `VARCHAR(25)`). However, when configuring default CUIDs in your Prisma ORM 2._x_ (or later versions) schema with `@default(cuid())` the generated ID values might exceed the limit of 25 characters (the maximum length might be 30 characters). To make your IDs proof for Prisma ORM 2._x_ (or later versions), you therefore need to adjust the column type to `VARCHAR(30)`. ### Example #### Prisma 1 datamodel ```graphql type User { id: ID! @id } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "User" ( id VARCHAR(25) PRIMARY KEY NOT NULL ); ``` #### Result of introspection in Prisma ORM 2._x_ and later versions ```prisma file=schema.prisma showLineNumbers model User { id String @id } ``` ### Workaround You can manually turn the `VARCHAR(25)` columns into `VARCHAR(30)`: ```sql ALTER TABLE "User" ALTER COLUMN "id" SET DATA TYPE character varying(30); ``` > **Note**: When fixing this issue with the [Upgrade CLI](/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade#prisma-1-upgrade-cli), the generated SQL statements will keep appearing in the Upgrade CLI even after you have changed the column types in the underlying database. This is a currently a limitation in the Upgrade CLI. ## Scalar lists (arrays) are maintained with extra table ### Problem In Prisma 1, you can define lists of _scalar_ types on your models. Under the hood, this is implemented with an extra table that keeps track of the values in the list. To remove the approach with the extra table which incurred hidden performance costs, Prisma ORM 2._x_ and later versions only support scalar lists only when they're natively supported by the database you use. At the moment, only [PostgreSQL supports scalar lists (arrays) natively](https://www.postgresql.org/docs/9.1/arrays.html). With PostgreSQL, you therefore can keep using scalar lists in Prisma ORM 2._x_ and later versions, but you'll need to perform a data migration to transfer the data from the extra table from Prisma 1 into an actual PostgreSQL array. ### Example #### Prisma 1 datamodel ```graphql type User { id: ID! @id coinflips: [Boolean!]! @scalarList(strategy: RELATION) } ``` #### Prisma 1 generated SQL migration ```sql CREATE TABLE "User" ( id VARCHAR(25) PRIMARY KEY NOT NULL ); CREATE TABLE "User_coinflips" ( "nodeId" VARCHAR(25) REFERENCES "User"(id), position INTEGER, value BOOLEAN NOT NULL, CONSTRAINT "User_coinflips_pkey" PRIMARY KEY ("nodeId", position) ); CREATE UNIQUE INDEX "User_coinflips_pkey" ON "User_coinflips"("nodeId" text_ops,position int4_ops); ``` #### Result of Prisma ORM 2 introspection ```prisma file=schema.prisma showLineNumbers model User { id String @id User_coinflips User_coinflips[] } model User_coinflips { nodeId String position Int value Boolean User User @relation(fields: [nodeId], references: [id]) @@id([nodeId, position]) } ``` Note that you can now generate Prisma Client and you'll be able to access the data from the scalar lists through the extra table. PostgreSQL users can alternatively migrate the data into a native PostgreSQL array and continue to benefit from the slicker Prisma Client API for scalar lists (read the section below for more info).
Expand for sample Prisma Client API calls To access the coinflips data, you will now have to always [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields) it in your queries: ```ts const user = await prisma.user.findUnique({ where: { id: 1 }, include: { coinflips: { orderBy: { position: 'asc' }, }, }, }) ``` > **Note**: The `orderBy` is important to retain the order of the list. This is the `result of the query: ```js { id: 1, name: 'Alice', coinflips: [ { id: 1, position: 1000, value: false }, { id: 2, position: 2000, value: true }, { id: 3, position: 3000, value: false }, { id: 4, position: 4000, value: true }, { id: 5, position: 5000, value: true }, { id: 6, position: 6000, value: false } ] } ``` To access just the boolean values from the list, you can `map` over the `coinflips` on `user` as follows: ```ts const currentCoinflips = user!.coinflips.map((cf) => cf.value) ``` > **Note**: The exclamation mark above means that you're _force unwrapping_ the `user` value. This is necessary because the `user` returned from the previous query might be `null`. Here's the value of `currentCoinflips` after the call to `map`: ```json [false, true, false, true, true, false] ```
### Workaround The following workaround is only available for PostgreSQL users! As scalar lists (i.e. [arrays](https://www.postgresql.org/docs/9.1/arrays.html)) are available as a native PostgreSQL feature, you can keep using the same notation of `coinflips: Boolean[]` in your Prisma schema. However, in order to do so you need to manually migrate the underlying data from the `User_coinflips` table into a PostgreSQL array. Here's how you can do that: 1. Add the new `coinflips` column to the `User` tables: ```sql ALTER TABLE "User" ADD COLUMN coinflips BOOLEAN[]; ``` 1. Migrate the data from `"User_coinflips".value` to `"User.coinflips"`: ```sql UPDATE "User" SET coinflips = t.flips FROM ( SELECT "nodeId", array_agg(VALUE ORDER BY position) AS flips FROM "User_coinflips" GROUP BY "nodeId" ) t where t."nodeId" = "User"."id"; ``` 1. To cleanup, you can delete the `User_coinflips` table: ```sql DROP TABLE "User_coinflips"; ``` You can now introspect your database and the `coinflips` field will be represented as an array in your new Prisma schema: ```prisma file=schema.prisma showLineNumbers model User { id String @id coinflips Boolean[] } ``` You can keep using Prisma Client as before: ```ts const user = await prisma.user.findUnique({ where: { id: 1 }, }) ``` This is the result from the API call: ```js { id: 1, name: 'Alice', coinflips: [ false, true, false, true, true, false ] } ``` --- # Upgrading the Prisma ORM layer URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-the-prisma-layer-mysql ## Overview This page explains the first step of your upgrade process: Taking your Prisma 1 configuration and upgrading it to Prisma ORM 2. Concretely, you will learn how to: 1. Add the Prisma ORM 2 CLI as a development dependency 1. Create your Prisma ORM 2 schema 1. Determine your connection URL and connect to your database 1. Introspect your database (that was so far managed with Prisma 1) 1. Use the [Prisma 1 Upgrade CLI](/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade#prisma-1-upgrade-cli) to resolve the [schema incompatibilities](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-mysql) in the new Prisma ORM 2 data model 1. Install and generate Prisma Client Once done with these steps, you can move on to the next guide that explains how you can upgrade the application layer to use Prisma Client for your database queries. > **Note**: During the upgrade process it can be helpful to get a graphical view on your database. It is therefore recommended to use a graphical database client to connect to your database, such as [TablePlus](https://tableplus.com/) or [Postico](https://eggerapps.at/postico/). ## 1. Install Prisma ORM 2 CLI The Prisma ORM 2 CLI is available as the [`prisma`](https://www.npmjs.com/package/prisma) package on npm and is invoked via the `prisma` command. Note that the former `prisma` command for Prisma 1 has been renamed to `prisma1`. You can learn more about this [here](https://www.prisma.io/blog/prisma-2-beta-b7bcl0gd8d8e#renaming-the-prisma2-cli). You can install the Prisma ORM 2 CLI in your Node.js project as follows (be sure to invoke this command in the directory where your `package.json` is located): ```terminal copy npm install prisma --save-dev ``` > **Note**: With Prisma 1, it was usually recommended to install the CLI globally. We now recommend to [install the Prisma CLI locally](/orm/tools/prisma-cli#installation) to prevent version conflicts. You can now use the local installation of the `prisma` CLI by prefixing it with `npx`: ```terminal npx prisma ``` If you're upgrading your entire project [all at once](/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade#upgrade-strategies), you can now also uninstall the Prisma 1 CLI (otherwise expand below): ```terminal # remove global installation npm uninstall -g prisma1 # remove local installation npm uninstall prisma1 ```
Expand if you want to keep using your Prisma 1 CLI side-by-side If you want to keep using the Prisma 1 CLI, it is recommend to remove your global installation of it and add the `prisma1` CLI as a development dependency: ```terminal # installs v1.34 of the Prisma 1 CLI npm uninstall -g prisma npm install prisma1 --save-dev ``` You can now invoke it as follows: ```terminal npx prisma1 ``` Note that if you need a CLI version smaller than 1.34 (e.g. 1.30), you can install it as follows: ```terminal # installs v1.30 of the Prisma 1 CLI npm uninstall -g prisma@1.30 npm install prisma@1.30 --save-dev ``` You can now invoke it as follows: ```terminal npx prisma ```
## 2. Create your Prisma ORM 2 schema For this guide, you'll first create a new Prisma schema using the `prisma init` command and then "fill" it with a data model using [introspection](/orm/prisma-schema/introspection). Run the following command to create your Prisma schema (note that this throws an error if you already have a folder called `prisma`): ```terminal copy npx prisma init ``` If you're seeing the following error, you need to rename your current `prisma` directory: ```no-lines ERROR A folder called prisma already exists in your project. Please try again in a project that is not yet using Prisma. ``` You can rename the current `prisma` directory to `prisma1` to make it clear that this holds the former Prisma 1 configuration: ```terminal copy mv prisma prisma1 ``` Now you can run `init` and it will succeed: ```terminal copy npx prisma init ``` It should print the following output: ```no-lines wrap ✔ Your Prisma schema was created at prisma/schema.prisma. You can now open it in your favorite editor. Next steps: 1. Set the `DATABASE_URL` in the `.env` file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started 2. Set the `provider` of your `datasource` block in `schema.prisma` to match your database: `postgresql`, `mysql` or `sqlite`. 3. Run `prisma db pull` to turn your database schema into a Prisma data model. 4. Run `prisma generate` to install Prisma Client. You can then start querying your database. More information in our documentation: https://pris.ly/d/getting-started ``` The command created a new folder called `prisma`, and two files: - `prisma/schema.prisma`: Your Prisma schema that specifies the [data source](/orm/prisma-schema/overview/data-sources), [generator](/orm/prisma-schema/overview/generators) and [data model](/orm/prisma-schema/data-model/models) (note that the data model doesn't exist yet, it will be generated via introspection). - `.env`: A [dotenv](https://github.com/motdotla/dotenv) file to configure your database [connection URL](/orm/reference/connection-urls). Your initial Prisma schema looks as follows: ```prisma file=schema.prisma showLineNumbers // This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema datasource db { provider = "mysql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } ``` With Prisma 1, you specify which language variant of Prisma Client you wanted to use in your `prisma.yml`. With Prisma ORM 2, this information is now specified inside the Prisma schema via a `generator` block. > **Note**: Unlike Prisma 1, the TypeScript and JavaScript variants of Prisma Client 2.0 use the _same_ generator called `prisma-client-js`. The generated types in `index.d.ts` are _always_ included, even in plain JavaScript projects. This enables feature like autocompletion in VS Code even when not using TypeScript. ## 3. Determine your connection URL and connect to your database With Prisma 1, the database connection is configured in the Docker Compose file that's used to launch the Prisma ORM server. The Prisma ORM server then exposes a GraphQL endpoint (via HTTP) that proxies all database requests from the Prisma Client application code. That HTTP endpoint is specified in your `prisma.yml`. With Prisma ORM 2, the HTTP layer isn't exposed any more and Prisma Client 2.0 is configured to run requests "directly" against the database (that is, requests are proxied by Prisma ORM's [query engine](/orm/more/under-the-hood/engines), but there isn't an extra server any more). So, as a next step you'll need to tell Prisma ORM 2 _what_ kind of database you use (MySQL or PostgreSQL) and _where_ it is located. First, you need to ensure that that `provider` field on the `datasource` block inside `schema.prisma` is configured to use the right database: - If you're using PostgreSQL, it needs to define the value `"postgresql"` in the `provider` field. - If you're using MySQL, it needs to define the value `"mysql"` in the `provider` field. Switch around with the tabs in the code block to see examples of both: ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` ```prisma datasource db { provider = "mysql" url = env("DATABASE_URL") } ``` With the `provider` field set, you can go ahead and configure the connection URL inside the `.env` file. Assume the database configuration in your Docker Compose file that you used to deploy your Prisma ORM server looks as follows: ```yml file=docker-compose.yml PRISMA_CONFIG: | port: 4466 databases: default: connector: mysql host: mysql port: 3306 user: root password: randompassword ``` Also assume your `endpoint` in `prisma.yml` is configured as follows: ```yml file=prisma.yml endpoint: http://localhost:4466/myproject/dev ``` Based on these connection details, you need to configure the `DATABASE_URL` environment variable inside your `.env` file as follows: ```bash file=.env DATABASE_URL="mysql://root:randompassword@localhost:3306/myproject@dev" ``` Note that the _database name_ in the connection URL is typically composed of your _service name_ and _service stage_ (which are part of the `endpoint` in `prisma.yml`), separated by the `@` character. Sometimes no service name and stage are specified in `prisma.yml`: ```yml file=prisma.yml endpoint: http://localhost:4466/ ``` In that case, the database name must be specified as follows: ```bash file=.env DATABASE_URL="mysql://root:randompassword@localhost:3306/default@default" ``` Learn more on the [Connection URLs](/orm/reference/connection-urls) page. ## 4. Introspect your database For the purpose of this guide, we'll use the following Prisma 1 data model (select the **SQL** tab below to see what the data model maps to in SQL): ```graphql type User { id: ID! @id email: String @unique name: String! role: Role! @default(value: CUSTOMER) jsonData: Json profile: Profile posts: [Post!]! } type Post { id: ID! @id createdAt: DateTime! @createdAt updatedAt: DateTime! @updatedAt title: String! content: String published: Boolean! @default(value: false) author: User @relation(link: TABLE) categories: [Category!]! } type Profile { id: ID! @id bio: String user: User! @relation(link: INLINE) } type Category { id: ID! @id name: String! posts: [Post!]! } enum Role { ADMIN CUSTOMER } ``` ```sql CREATE TABLE"User" ( id character varying(25) PRIMARY KEY, email text, name text NOT NULL, role text NOT NULL, "jsonData" text ); CREATE UNIQUE INDEX "User_pkey" ON"User"(id text_ops); CREATE UNIQUE INDEX "default$default.User.email._UNIQUE" ON"User"(email text_ops); CREATE TABLE"Post" ( id character varying(25) PRIMARY KEY, title text NOT NULL, published boolean NOT NULL, "createdAt" timestamp(3) without time zone NOT NULL, "updatedAt" timestamp(3) without time zone NOT NULL, content text ); CREATE UNIQUE INDEX "Post_pkey" ON"Post"(id text_ops); CREATE TABLE"Profile" ( id character varying(25) PRIMARY KEY, bio text, user character varying(25) REFERENCES"User"(id) ON DELETE SET NULL ); CREATE UNIQUE INDEX "Profile_pkey" ON"Profile"(id text_ops); CREATE TABLE"Category" ( id character varying(25) PRIMARY KEY, name text NOT NULL ); CREATE UNIQUE INDEX "Category_pkey" ON"Category"(id text_ops); CREATE TABLE"_PostToUser" ( "A" character varying(25) NOT NULL REFERENCES"Post"(id) ON DELETE CASCADE, "B" character varying(25) NOT NULL REFERENCES"User"(id) ON DELETE CASCADE ); CREATE UNIQUE INDEX "_PostToUser_AB_unique" ON"_PostToUser"("A" text_ops,"B" text_ops); CREATE INDEX "_PostToUser_B" ON"_PostToUser"("B" text_ops); CREATE TABLE"_CategoryToPost" ( "A" character varying(25) NOT NULL REFERENCES"Category"(id) ON DELETE CASCADE, "B" character varying(25) NOT NULL REFERENCES"Post"(id) ON DELETE CASCADE ); CREATE UNIQUE INDEX "_CategoryToPost_AB_unique" ON"_CategoryToPost"("A" text_ops,"B" text_ops); CREATE INDEX "_CategoryToPost_B" ON"_CategoryToPost"("B" text_ops); ``` Note that this data model has three [relations](/orm/prisma-schema/data-model/relations): - 1-1: `User` ↔ `Profile` - 1-n: `User` ↔ `Post` (maintained via the `_PostToUser` relation table) - m-n: `Post` ↔ `Category` (maintained via the `_CategoryToPost` relation table) Now you can run Prisma ORM's introspection against your database with the following command: ```terminal copy npx prisma db pull ``` Here's a graphical illustration for what happens when `db pull` is invoked: ![Introspect your database](/img/orm/prisma-db-pull-generate-schema.png) For the above Prisma 1 datamodel, this results in the following Prisma ORM 2 schema (note that the models have been reordered to match the initial order of the Prisma 1 datamodel): ```prisma file=schema.prisma showLineNumbers model User { id String @id @default(cuid()) email String? @unique name String role String jsonData String? Profile Profile[] Post Post[] } model Post { id String @id @default(cuid()) createdAt DateTime updatedAt DateTime title String content String? published Boolean Category Category[] User User[] } model Profile { id String @id @default(cuid()) bio String? user String? @unique User User? @relation(fields: [user], references: [id]) } model Category { id String @id @default(cuid()) name String Post Post[] } ``` While this is already a valid Prisma ORM 2 schema, it lacks a number of _features_ that were part of its Prisma 1 equivalent: - no auto-generated date values for the `createdAt` and `updatedAt` fields on `Post` - no default value for the `role` field on `User` - no default value for the `published` field on `Post` There further are a number of inconsistencies which result in a less idiomatic/ergonomic Prisma Client API: - `User` ↔ `Profile` is a 1-n instead of 1-1 relation - `User` ↔ `Post` is a m-n instead of 1-n relation - relation fields are uppercased (e.g. `Profile` and `Post` on `User`) - the `jsonData` field on `User` is of type `String` instead of `Json` - the `role` field on `User` is of type `String` instead of `Role`, the `enum` definition for role is missing altogether While these inconsistencies don't actually impact the "feature set" you'll have available in your Prisma Client API, they make you lose certain constraints/guarantees that were present before. For example, Prisma ORM now won't guarantee that a `User` is connected to _at most_ one `Profile` because the relation between the tables was recognized as 1-n during introspection, so one `User` record _could_ now get connected to multiple `Profile` records. Another issue is that you can store whatever text for the `jsonData` and `role` fields, regardless of whether it's valid JSON or represents a value of the `Role` enum. To learn more about these inconsistencies check out the [Schema incompatibilities](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-mysql) page. In the following, we'll go through these incompatibilities and fix them one by one using the Prisma schema upgrade CLI. ## 5. Use the Prisma schema upgrade CLI to resolve schema incompatibilities The [Prisma 1 Upgrade CLI](/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade#prisma-1-upgrade-cli) is an interactive tool that helps you upgrading your Prisma schema and ironing out most of the inconsistencies listed above. The Prisma 1 Upgrade CLI works in two major phases: 1. Fix the database schema via plain SQL 1. Add missing attributes to the Prisma ORM 2 schema and other schema fixes During the first phase, it will generate and print a number of SQL statements that you should run against your database to adjust the database schema. You can either run all of the statements or a subset of them before continuing to the second phase. During the second phase, you don't need to do anything manually. The Upgrade CLI will make changes to your Prisma schema by adding certain Prisma ORM-level attributes (like `@default(cuid))` or `@updatedAt`), adjusting the names of relation fields to match the ones from your Prisma 1 datamodel and ensure 1-1-relations that were required on both sides in your Prisma 1 datamodel are also required in the Prisma ORM 2 schema. Note that **you can start over at any time during the process** and go back from the second to the first phase. In this illustration, the green area shows the first phase, the blue area shows the second phase. Note that you can optionally run `prisma db pull` in between the phases to update your Prisma ORM data model: ![Fixing the schema incompatibilities](./images/fix-schema-incompatibilities.png) To use the Upgrade CLI, you can either install it locally in your project, or invoke it once without installation using `npx` as done here: ```terminal copy npx prisma-upgrade prisma1/prisma.yml prisma/schema.prisma ``` The CLI will greet you with the following message: ```no-lines wrap ◮ Welcome to the interactive Prisma Upgrade CLI that helps with the upgrade process from Prisma 1 to Prisma ORM 2. Please read the docs to learn more about the upgrade process: https://pris.ly/d/how-to-upgrade ➤ Goal The Upgrade CLI helps you resolve the schema incompatibilities between Prisma 1 and Prisma ORM 2. Learn more in the docs: https://pris.ly/d/schema-incompatibilities ➤ How it works Throughout the process, you'll need to adjust your database schema by sending SQL statements to it. The SQL statements are provided by the Upgrade CLI. Note that the Upgrade CLI never makes changes to your database, you are in full control over any operations that are executed against it. You can stop and re-run the Upgrade CLI at any time. These are the different steps of the upgrade process: 1. The Upgrade CLI generates SQL commands for you to run on your database. 2. You run the SQL commands against your database. 3. You run the `npx prisma db pull` command again. 4. You run the `npx prisma-upgrade` command again. 5. The Upgrade CLI adjusts the Prisma ORM 2 schema by adding missing attributes. ➤ Note It is recommended that you make a full backup of your existing data before starting the upgrade process. If possible, the migration should be performed in a staging environment before executed against a production environment. ➤ Help If you have any questions or run into any problems along the way, please create an issue at: https://github.com/prisma/prisma1-upgrade/issues/new Are you ready? [Y/n] ``` Press the Y button, then confirm by hitting RETURN on your keyboard to continue. Once you confirmed, the CLI outputs the SQL statements you should be running against your database: ```no-lines wrap ➤ Adjust your database schema Run the following SQL statements against your database: Fix columns with ENUM data types https://pris.ly/d/schema-incompatibilities#enums-are-represented-as-text-in-database ALTER TABLE `User` CHANGE `role` `role` ENUM('ADMIN', 'CUSTOMER') NOT NULL; Add missing `DEFAULT` constraints to the database https://pris.ly/d/schema-incompatibilities#default-values-arent-represented-in-database ALTER TABLE `User` CHANGE `role` `role` ENUM('ADMIN', 'CUSTOMER') NOT NULL DEFAULT 'CUSTOMER'; ALTER TABLE `Post` CHANGE `published` `published` TINYINT(1) NOT NULL DEFAULT 0; Fix columns with JSON data types https://pris.ly/d/schema-incompatibilities#json-type-is-represented-as-text-in-database ALTER TABLE `User` CHANGE `jsonData` `jsonData` JSON ; Replicate `@createdAt` behavior in Prisma ORM 2.0 https://pris.ly/d/schema-incompatibilities#createdat-isnt-represented-in-database ALTER TABLE `Post` CHANGE `createdAt` `createdAt` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP; Fix 1-1 relations by adding `UNIQUE` constraints https://pris.ly/d/schema-incompatibilities#inline-1-1-relations-are-recognized-as-1-n-missing-unique-constraint ALTER TABLE `Profile` ADD UNIQUE (`user`); Migrate IDs from varchar(25) to varchar(30) https://pris.ly/d/schema-incompatibilities#mismatching-cuid-length SET FOREIGN_KEY_CHECKS=0; ALTER TABLE `Category` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL; ALTER TABLE `Post` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL; ALTER TABLE `Profile` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL; ALTER TABLE `Profile` CHANGE `user` `user` char(30) CHARACTER SET utf8 ; ALTER TABLE `User` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL; SET FOREIGN_KEY_CHECKS=1; ➤ Breaking changes detected In order to fully optimize your database schema, you'll need to run a few SQL statements that can break your Prisma 1 setup. Note that these changes are optional and if you are upgrading gradually and running Prisma 1 and Prisma ORM 2 side-by-side, you should not perform these changes yet. Instead, you can perform them whenever you are ready to completely remove Prisma 1 from your project. If you are upgrading all at once, you can safely perform these changes now. Learn more in the docs: https://pris.ly/d/how-to-upgrade' ``` > **Note**: If you're seeing the note about breaking changes, you can ignore it for now. We'll discuss it later. The shown SQL statements are categorized into a number of "buckets", all aiming to resolve a certain [schema incompatibility](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-mysql): - Fix columns with ENUM data types - Add missing `DEFAULT` constraints to the database - Fix columns with JSON data types - Replicate `@createdAt` behavior in Prisma 2 - Fix 1-1 relations by adding `UNIQUE` constraints As a next step, you can start sending the SQL statements to your database. Note that all of these changes are non-breaking and you'll be able to continue using Prisma 1 side-by-side with Prisma ORM 2. The next sections cover the different kinds of SQL statements to be sent to your database individually. ### 5.1. Fix the database schema via plain SQL (non-breaking) In this section, we'll walk through the printed SQL statements and run them against the database one by one. ### 5.1.1. Fix columns with ENUM data types The first thing the tool does is help you ensure that `enum` definitions in your Prisma 1 datamodel will be represented as actual `ENUM` types in the underlying database, right now they are represented as plain strings (e.g. as `MEDIUMTEXT` in MySQL). The CLI currently shows the following output: ```no-lines wrap Fix columns with ENUM data types https://pris.ly/d/schema-incompatibilities#enums-are-represented-as-text-in-database ALTER TABLE `User` CHANGE `role` `role` ENUM('ADMIN', 'CUSTOMER') NOT NULL; ``` Go ahead and run these statements against your database now. ![Altering columns to use ENUM with SQL](./images/altering-columns-to-use-enum.png) ### 5.1.2. Add missing `DEFAULT` constraints to the database Next, the Upgrade CLI helps you resolve the issue that [default values aren't represented in the database](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-mysql#default-values-arent-represented-in-database) by generating SQL statements that add the respective `DEFAULT` constraints directly to the database. In this case, two `DEFAULT` constraints are missing which are suggested by the tool: ```no-lines wrap Add missing `DEFAULT` constraints to the database https://pris.ly/d/schema-incompatibilities#default-values-arent-represented-in-database ALTER TABLE `User` CHANGE `role` `role` ENUM('ADMIN', 'CUSTOMER') NOT NULL DEFAULT 'CUSTOMER'; ALTER TABLE `Post` CHANGE `published` `published` TINYINT(1) NOT NULL DEFAULT 0; ``` You can now run these SQL statements against your database either using a command line client or a GUI like TablePlus: ![TablePlus GUI](./images/TablePlus-GUI.png) ### 5.1.3. Fix columns with JSON data types Next, the tool helps you ensure that `Json` fields in your Prisma 1 datamodel will be represented as `JSON` columns in the underlying database, right now they are represented as plain strings (e.g. as `MEDIUMTEXT` in MySQL). Changing the column type to `JSON` will ensure that the field is properly recognized as `Json` during Prisma ORM 2 introspection. The CLI currently shows the following output: ```no-lines wrap Fix columns with JSON data types https://pris.ly/d/schema-incompatibilities#json-type-is-represented-as-text-in-database ALTER TABLE `User` CHANGE `jsonData` `jsonData` JSON ; ``` You can now run these SQL statements against your database either using a command line client or a GUI like TablePlus: ![TablePlus GUI](./images/fix-columns-with-json-data-types.png) ### 5.1.4. Replicate `@createdAt` behavior in Prisma ORM 2 The next thing the tools does is help you resolve the issue that the behavior of [`@createdAt` isn't represented in database](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-mysql#default-values-arent-represented-in-database) The CLI currently shows the following output: ```no-lines wrap Replicate `@createdAt` behavior in Prisma ORM 2.0 https://pris.ly/d/schema-incompatibilities#createdat-isnt-represented-in-database ALTER TABLE `Post` CHANGE `createdAt` `createdAt` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP; ``` You can now run these SQL statements against your database either using a command line client or a GUI like TablePlus. ### 5.1.5. Fix 1-1 relations by adding `UNIQUE` constraints Now, the tool will help you [turn the current 1-n relation between `User` ↔ `Profile` back into a 1-1 relation](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-mysql#inline-1-1-relations-are-recognized-as-1-n-missing-unique-constraint) by adding a `UNIQUE` constraint to the foreign key column called `user` (named after the relation field in the Prisma 1 datamodel) in the database. The CLI currently shows the following output: ```no-lines wrap Fix 1-1 relations by adding `UNIQUE` constraints https://pris.ly/d/schema-incompatibilities#inline-1-1-relations-are-recognized-as-1-n-missing-unique-constraint ALTER TABLE `Profile` ADD UNIQUE (`user`); ``` You can now run these SQL statements against your database either using a command line client or a GUI like TablePlus. ### 5.1.6. Fix mismatch of CUID length > **Note**: These SQL statements will keep appearing in the Upgrade CLI even after you have changed the column types in the underlying database. This is a currently a limitation in the Upgrade CLI. Finally, the tool will help you [turn the current ID columns of type `VARCHAR(25)` into `VARCHAR(30)`](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-mysql#mismatching-cuid-length) by adding a `UNIQUE` constraint to the foreign key column called `user` (named after the relation field in the Prisma 1 datamodel) in the database. The CLI currently shows the following output: ```no-lines wrap Migrate IDs from varchar(25) to varchar(30) https://pris.ly/d/schema-incompatibilities#mismatching-cuid-length SET FOREIGN_KEY_CHECKS=0; ALTER TABLE `Category` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL; ALTER TABLE `Post` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL; ALTER TABLE `Profile` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL; ALTER TABLE `Profile` CHANGE `user` `user` char(30) CHARACTER SET utf8 ; ALTER TABLE `User` CHANGE `id` `id` char(30) CHARACTER SET utf8 NOT NULL; SET FOREIGN_KEY_CHECKS=1; ``` You can now run these SQL statements against your database either using a command line client or a GUI like TablePlus. ### 5.1.7. Breaking changes detected In case the Upgrade CLI has printed a note about breaking changes, your database schema needs some adjustments that will break Prisma 1 compatibility in order to be fully optimized. If there are no breaking changes detected, you can [skip forward to section 5.2](#52-re-introspect-your-database-to-update-your-prisma-schema) Depending on your [upgrade strategy](/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade#upgrade-strategies), you can either perform these changes now or skip to the next phase of the Upgrade CLI: - If you are following the gradual side-by-side upgrade strategy, do not perform these changes yet since they will break your Prisma 1 setup. In that case, you can continue to the next phase of the Upgrade CLI by typing n and hitting RETURN. - If you are following the all at once upgrade strategy, you can perform these changes now. In that case, continue by typing Y and hitting RETURN. ### 5.2. Fix the database schema via plain SQL (breaking) In this section, you'll resolve the schema incompatibilities that are breaking your Prisma 1 setup. Do not perform these changes if you are still running Prisma 1 in your project! ### 5.2.1. Fix incorrect m-n relations Now, the Upgrade CLI helps you fix all 1-1 and 1-n relations that Prisma 1 represents with relation tables and that [currently only exist as m-n relations](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-mysql#all-non-inline-relations-are-recognized-as-m-n) in your new Prisma ORM 2 schema. Concretely, this is the case for the `User` ↔ `Post` relation which currently is defined as m-n but _should_ really be a 1-n relation. To fix this, you'll need to perform the following migration: 1. Create a new foreign key column on `Post` to link directly to the `User` table. 1. Migrate the foreign key values from the relation table into the new foreign key column on `Post`. 1. Delete the relation table. These instructions are now printed by the CLI: ```no-lines wrap ➤ Adjust your database schema Run the following SQL statements against your database: Fix one-to-many table relations https://pris.ly/d/schema-incompatibilities#all-non-inline-relations-are-recognized-as-m-n ALTER TABLE `Post` ADD COLUMN `authorId` char(25) CHARACTER SET utf8 ; ALTER TABLE `Post` ADD CONSTRAINT author FOREIGN KEY (`authorId`) REFERENCES `User`(`id`); UPDATE `Post`, `_PostToUser` SET `Post`.`authorId` = `_PostToUser`.B where `_PostToUser`.A = `Post`.`id`; DROP TABLE `_PostToUser`; ➤ Next Steps After you executed one or more of the above SQL statements against your database, please run the following two commands to refresh your Prisma ORM 2 Schema and check the changes. 1. Run `npx prisma db pull` again to refresh your Prisma ORM 2 schema. 2. Run `npx prisma-upgrade` again. If you can't or don't want to execute the remaining SQL statements right now, you can skip to the last step where the Upgrade CLI adds missing attributes to your Prisma ORM 2 schema that are not picked up by introspection. Skip to the last step? [Y/n]? ``` For this fix, you'll need to run three SQL statements: 1. Create new column `authorId` on the `Post` table. This column should be a _foreign key_ that references the `id` field of the `User` table: ```sql no-lines ALTER TABLE `Post` ADD COLUMN `authorId` char(25) CHARACTER SET utf8 ; ALTER TABLE `Post` ADD CONSTRAINT author FOREIGN KEY (`authorId`) REFERENCES `User`(`id`); ``` 1. Write a SQL query that reads all the rows from the `_PostToUser` relation table and for each row: 1. Finds the respective `Post` record by looking up the value from column `A` 1. Inserts the value from column `B` as the value for `authorId` into that `Post` record ```sql no-lines UPDATE `Post`, `_PostToUser` SET `Post`.`authorId` = `_PostToUser`.B where `_PostToUser`.A = `Post`.`id`; ``` 1. Delete the `_PostToUser` relation table ```sql no-lines DROP TABLE `_PostToUser`; ``` ![Fixing incorrect m-n relations with SQL](./images/fix-incorrect-m-n-relations-sql.png) After these commands, the user ID values of the records from column `B` of the relation table are migrated to the new `authorId` column. ### 5.2. Re-introspect your database to update your Prisma schema At this point, you've resolved the schema incompatibilities with the Upgrade CLI. You can now exit the Upgrade CLI for now by typing n and hitting RETURN. In this section, you'll update your Prisma schema with another introspection round. This time, the previous flaws of the Prisma schema will be resolved because the database schema has been adjusted: ```terminal copy npx prisma db pull ``` This time, the resulting Prisma schema looks as follows: ```prisma file=schema.prisma showLineNumbers model User { id String @id name String email String? @unique jsonData Json? role Role @default(CUSTOMER) Post Post[] Profile Profile? } model Post { id String @id createdAt DateTime @default(now()) updatedAt DateTime title String content String? published Boolean @default(false) authorId String? User User? @relation(fields: [authorId], references: [id]) Category Category[] @relation(references: [id]) } model Category { id String @id name String Post Post[] @relation(references: [id]) } model Profile { bio String? id String @id user String? @unique User User? @relation(fields: [user], references: [id]) } enum Role { ADMIN CUSTOMER } ``` This schema has most issues resolved, but it still lacks the following: ### 5.2. Add missing attributes to the Prisma 2 schema and other schema fixes The CLI now prints the following: ```no-lines wrap ➤ What happens next As a last step, some final adjustments will be made to your Prisma ORM 2 schema to carry over some Prisma ORM-level attributes that aren't picked up by introspection. As a last step, some final adjustments will be made to your Prisma ORM 2.0 schema to carry over some Prisma ORM-level attributes that aren't picked up by introspection. Warning Your current Prisma ORM 2.0 schema will be overwritten, so please make sure you have a backup! Are you ready? [Y/n] ``` At this point, you either ran all the SQL statement that were printed by the CLI or you skipped some of them. Either way, you can now move on the last step and let the Upgrade CLI add the missing Prisma ORM 2 attributes. Typically these are the following: - `@default(cuid())` for your `@id` fields - `@updatedAt` for any fields that were using this attribute in Prisma 1 - `@map` and `@@map` as replacements for `@db` and `@@db` from Prisma 1 In that step, the Upgrade CLI also fixes other issues that occurred in the transition to Prisma ORM 2: - it makes sure that 1-1-relations that were required on both sides in Prisma 1 are also required in your Prisma ORM 2 schema - it renames relation fields to the same names they had in your Prisma 1 datamodel ([coming soon](https://github.com/prisma/prisma1-upgrade/issues/25)) To apply these changes, you can re-run the Upgrade CLI: ```terminal copy npx prisma-upgrade prisma1/prisma.yml prisma/schema.prisma ``` If you did not resolve all schema incompatibilities, the Upgrade CLI now prints the remaining SQL statements (as well as the ones for migrating IDs). You can just ignore them at this point and continue to the last step by continuously typing Y and hitting RETURN when prompted. If you did resolve all schema incompatibilities, no SQL statements will be printed and the Upgrade CLI only outputs the following: ```no-lines wrap $ npx prisma-upgrade prisma1/prisma.yml prisma/schema.prisma ➤ Next Steps After you executed one or more of the previous SQL statements against your database, please run the following two commands to refresh your Prisma ORM 2 schema and check the changes. 1. Run `npx prisma db pull` again to refresh your Prisma ORM 2 schema. 2. Run `npx prisma-upgrade` again. If you can't or don't want to execute the remaining SQL statements right now, you can skip to the last step where the Upgrade CLI adds missing attributes to your Prisma ORM 2 schema that are not picked up by introspection. Skip to the last step? [Y/n]? ``` One more time, type Y and hit RETURN to confirm. The final prompt of the Upgrade CLI now asks you to confirm the above mentioned changes it will make to your Prisma schema: ```no-lines wrap ➤ What happens next As a last step, some final adjustments will be made to your Prisma ORM 2 schema to carry over some Prisma ORM-level attributes that aren't picked up by introspection. As a last step, some final adjustments will be made to your Prisma ORM 2.0 schema to carry over some Prisma ORM-level attributes that aren't picked up by introspection. Warning Your current Prisma ORM 2.0 schema will be overwritten, so please make sure you have a backup! Are you ready? [Y/n] ``` One last time, type Y and hit RETURN to confirm. This is the final output of the Upgrade CLI: ```no-lines Updating prisma/schema.prisma... Done updating prisma/schema.prisma! ✔ Congratulations, you're all set! ➤ Note If you didn't execute all generated SQL commands against your database, you can re-run the Upgrade CLI at any time. Note that the Upgrade CLI doesn't resolve all of the schema incompatibilities between Prisma 1 and Prisma ORM 2. If you want to resolve the remaining ones, you can do so manually by following this guide: https://pris.ly/d/upgrading-the-prisma-layer ➤ Next steps Otherwise you can continue your upgrade process by installing Prisma Client 2: npm install @prisma/client You can find guides for different upgrade scenarios in the docs: https://pris.ly/d/upgrade-from-prisma-1 ``` ### 5.3. Final result The final version of the Prisma schema should look as follows: ```prisma file=schema.prisma showLineNumbers model User { id String @id @default(cuid()) name String email String? @unique jsonData Json? role Role @default(CUSTOMER) Post Post[] Profile Profile? } model Post { id String @id @default(cuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String content String? published Boolean @default(false) authorId String? User User? @relation(fields: [authorId], references: [id]) Category Category[] @relation(references: [id]) } model Profile { id String @id @default(cuid()) bio String? user String? @unique User User? @relation(fields: [user], references: [id]) } model Category { id String @id @default(cuid()) name String Post Post[] @relation(references: [id]) } enum Role { ADMIN CUSTOMER } ``` ### 5.4. Rename relation fields One thing you'll notice with this version of the Prisma ORM 2 schema is that all [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are named after their respective models, e.g: ```prisma file=schema.prisma showLineNumbers model User { Post Post[] Profile Profile? } model Post { User User? @relation(fields: [authorId], references: [id]) Category Category[] @relation(references: [id]) } model Profile { User User? @relation(fields: [user], references: [id]) } model Category { Post Post[] @relation(references: [id]) } ``` This is not ideal and you can in fact manually rename all of them to their previous versions! Because all relation fields are _virtual_, meaning they don't _manifest_ in the database, you can name them whatever you like. In this case, all relation fields are lowercased and sometimes pluralized. Here's what they look like after the rename: ```prisma file=schema.prisma showLineNumbers model User { posts Post[] profile Profile? } model Post { author User? @relation(fields: [authorId], references: [id]) categories Category[] @relation(references: [id]) } model Profile { user String? @unique owner User? @relation(fields: [user], references: [id]) } model Category { posts Post[] @relation(references: [id]) } ``` > **Note**: For the 1-1-relation between `User` and `Profile` it was not possible to set the old name `user` for the relation field. This is because there'd be a naming conflict with the already existing [relation scalar](/orm/prisma-schema/data-model/relations#annotated-relation-fields) field that holds the foreign key. In that case, you can choose a different name or alternatively rename the foreign key column directly in the database via SQL. ### 5.5. Resolving remaining schema incompatibilities There are a few schema incompatibilities that were not yet resolved by the Upgrade CLI. At this point you still haven't fixed [scalar lists](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-mysql#scalar-lists-arrays-are-maintained-with-extra-table). You can find the recommended workarounds for this and others on the [Schema incompatibilities](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-mysql) page. ## 6. Install and generate Prisma Client Now that you have your Prisma ORM 2 schema ready, you can install Prisma Client with the following command: ```terminal copy npm install @prisma/client ``` ## 7. Next steps Congratulations, you have now upgraded your Prisma ORM layer to Prisma ORM 2! From here on, you can move on to update your application code using one of the following guides: - [Old to new Nexus](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-nexus-prisma-to-nexus): Choose this guide if you're currently running Prisma 1 with GraphQL Nexus. - [prisma-binding to Nexus](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-prisma-binding-to-nexus): Choose this guide if you're currently running Prisma 1 with `prisma-binding` and want to upgrade to [Nexus](https://nexusjs.org/) (and TypeScript). - [prisma-binding to SDL-first](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-prisma-binding-to-sdl-first): Choose this guide if you're currently running Prisma 1 with `prisma-binding` and want to upgrade to an [SDL-first](https://www.prisma.io/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3) GraphQL server. - [REST API](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-a-rest-api): Choose this guide if you're currently running Prisma 1 using Prisma Client 1 and are building a REST API. ## Bonus: Prisma Client API comparison This section contains a high-level and side-by-side comparison of the Prisma Client APIs of Prisma 1 and Prisma ORM 2. For more details about the new Prisma Client API, you can explore the [Prisma Client](/orm/prisma-client) docs. ### Reading single records ```ts const user = await prisma.user({ id: 1 }) ``` ```ts await prisma.user.findUnique({ where: { id: 1 }, }) ``` ### Reading lists of records ```ts const user = await prisma.users() ``` ```ts await prisma.user.findMany() ``` ### Filtering lists ```ts const users = await prisma.users({ where: { name: 'Alice', }, }) ``` ```ts await prisma.user.findMany({ where: { name: 'Alice', }, }) ``` ### Paginating lists ```ts const posts = await prisma.posts({ skip: 5, first: 10, }) ``` ```ts await prisma.user.findMany({ skip: 5, take: 10, }) ``` > **Note**: You can learn more about the new pagination API in the respective [release notes](https://github.com/prisma/prisma/releases/tag/2.0.0-beta.7) or the [Pagination](/orm/prisma-client/queries/pagination) page in the docs. ### Sorting lists ```ts await prisma.posts({ orderBy: 'title_ASC', }) ``` ```ts await prisma.posts({ orderBy: { title: 'asc', }, }) ``` ### Creating records ```ts await prisma.createUser({ name: 'Alice', }) ``` ```ts await prisma.user.create({ data: { name: 'Alice', }, }) ``` ### Updating records ```ts await prisma.updateUser({ where: { id: 1 }, data: { name: 'James', email: 'james@prisma.io', }, }) ``` ```ts await prisma.user.update({ where: { id: 1 }, data: { name: 'James', email: 'james@prisma.io', }, }) ``` ### Deleting records ```ts await prisma.deleteUser({ id: 1 }) ``` ```ts await prisma.user.delete({ where: { id: 1 }, }) ``` ### Selecting fields & loading relations In Prisma 1, the only ways to select specific fields and/or load relations of an object was by using the string-based `$fragment` and `$graphql` functions. With Prisma ORM 2, this is now done in a clean and type-safe manner using [`select`](/orm/prisma-client/queries/select-fields#select-specific-fields) and [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields). Another benefit of this approach is that you can use `select` and `include` on _any_ Prisma Client query, e.g. `findUnique`, `findMany`, `create`, `update`, `delete`, ... ```ts await prisma.user({ id: 1 }).$fragment(` fragment NameAndEmail on User { id email }` `) ``` ```ts await prisma.user.findUnique({ where: { id: 1 }, select: { id: true, email: true, }, }) ``` As an example, creating a new record and only retrieving the `id` in the returned object was not possible in Prisma 1. With Prisma ORM 2 you can achieve this as follows: ```ts await prisma.user.create({ data: { name: 'Alice', }, select: { id: true, }, }) ``` --- # Upgrading the Prisma ORM layer URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-the-prisma-layer-postgresql ## Overview This page explains the first step of your upgrade process: Taking your Prisma 1 configuration and upgrading it to Prisma ORM 2. Concretely, you will learn how to: 1. Add the Prisma ORM 2 CLI as a development dependency 1. Create your Prisma ORM 2 schema 1. Determine your connection URL and connect to your database 1. Introspect your database (that was so far managed with Prisma 1) 1. Use the [Prisma 1 Upgrade CLI](/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade#prisma-1-upgrade-cli) to resolve the [schema incompatibilities](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql) in the new Prisma ORM 2 data model 1. Install and generate Prisma Client Once done with these steps, you can move on to the next guide that explains how you can upgrade the application layer to use Prisma Client for your database queries. > **Note**: During the upgrade process it can be helpful to get a graphical view on your database. It is therefore recommended to use a graphical database client to connect to your database, such as [TablePlus](https://tableplus.com/) or [Postico](https://eggerapps.at/postico/). ## 1. Install Prisma ORM 2 CLI The Prisma ORM 2 CLI is available as the [`prisma`](https://www.npmjs.com/package/prisma) package on npm and is invoked via the `prisma` command. Note that the former `prisma` command for Prisma 1 has been renamed to `prisma1`. You can learn more about this [here](https://www.prisma.io/blog/prisma-2-beta-b7bcl0gd8d8e#renaming-the-prisma2-cli). You can install the Prisma ORM 2 CLI in your Node.js project as follows (be sure to invoke this command in the directory where your `package.json` is located): ```terminal copy npm install prisma --save-dev ``` > **Note**: With Prisma 1, it was usually recommended to install the CLI globally. We now recommend to [install the Prisma CLI locally](/orm/tools/prisma-cli#installation) to prevent version conflicts. You can now use the local installation of the `prisma` CLI by prefixing it with `npx`: ```terminal npx prisma ``` If you're upgrading your entire project [all at once](/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade#upgrade-strategies), you can now also uninstall the Prisma 1 CLI (otherwise expand below): ```terminal # remove global installation npm uninstall -g prisma1 # remove local installation npm uninstall prisma1 ```
Expand if you want to keep using your Prisma 1 CLI side-by-side If you want to keep using the Prisma 1 CLI, it is recommend to remove your global installation of it and add the `prisma1` CLI as a development dependency: ```terminal # installs v1.34 of the Prisma 1 CLI npm uninstall -g prisma npm install prisma1 --save-dev ``` You can now invoke it as follows: ```terminal npx prisma1 ``` Note that if you need a CLI version smaller than 1.34 (e.g. 1.30), you can install it as follows: ```terminal # installs v1.30 of the Prisma 1 CLI npm uninstall -g prisma@1.30 npm install prisma@1.30 --save-dev ``` You can now invoke it as follows: ```terminal npx prisma ```
## 2. Create your Prisma ORM 2 schema For this guide, you'll first create a new Prisma schema using the `prisma init` command and then "fill" it with a data model using [introspection](/orm/prisma-schema/introspection). Run the following command to create your Prisma schema (note that this throws an error if you already have a folder called `prisma`): ```terminal copy npx prisma init ``` If you're seeing the following error, you need to rename your current `prisma` directory: ```no-lines ERROR A folder called prisma already exists in your project. Please try again in a project that is not yet using Prisma. ``` You can rename the current `prisma` directory to `prisma1` to make it clear that this holds the former Prisma 1 configuration: ```terminal copy mv prisma prisma1 ``` Now you can run `init` and it will succeed: ```terminal copy npx prisma init ``` It should print the following output: ```no-lines wrap ✔ Your Prisma schema was created at prisma/schema.prisma. You can now open it in your favorite editor. Next steps: 1. Set the `DATABASE_URL` in the `.env` file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started 2. Set the `provider` of your `datasource` block in `schema.prisma` to match your database: `postgresql`, `mysql` or `sqlite`. 3. Run `prisma db pull` to turn your database schema into a Prisma data model. 4. Run `prisma generate` to install Prisma Client. You can then start querying your database. More information in our documentation: https://pris.ly/d/getting-started ``` The command created a new folder called `prisma`, and two files: - `prisma/schema.prisma`: Your Prisma schema that specifies the [data source](/orm/prisma-schema/overview/data-sources), [generator](/orm/prisma-schema/overview/generators) and [data model](/orm/prisma-schema/data-model/models) (note that the data model doesn't exist yet, it will be generated via introspection). - `.env`: A [dotenv](https://github.com/motdotla/dotenv) file to configure your database [connection URL](/orm/reference/connection-urls). Your initial Prisma schema looks as follows: ```prisma file=schema.prisma showLineNumbers // This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } ``` With Prisma 1, you specify which language variant of Prisma Client you wanted to use in your `prisma.yml`. With Prisma ORM 2, this information is now specified inside the Prisma schema via a `generator` block. > **Note**: Unlike Prisma 1, the TypeScript and JavaScript variants of Prisma Client 2.0 use the _same_ generator called `prisma-client-js`. The generated types in `index.d.ts` are _always_ included, even in plain JavaScript projects. This enables feature like autocompletion in VS Code even when not using TypeScript. ## 3. Determine your connection URL and connect to your database With Prisma 1, the database connection is configured in the Docker Compose file that's used to launch the Prisma ORM server. The Prisma ORM server then exposes a GraphQL endpoint (via HTTP) that proxies all database requests from the Prisma Client application code. That HTTP endpoint is specified in your `prisma.yml`. With Prisma ORM 2, the HTTP layer isn't exposed any more and Prisma Client 2.0 is configured to run requests "directly" against the database (that is, requests are proxied by Prisma ORM's [query engine](/orm/more/under-the-hood/engines), but there isn't an extra server any more). So, as a next step you'll need to tell Prisma ORM 2 _what_ kind of database you use (MySQL or PostgreSQL) and _where_ it is located. First, you need to ensure that that `provider` field on the `datasource` block inside `schema.prisma` is configured to use the right database: - If you're using PostgreSQL, it needs to define the value `"postgresql"` in the `provider` field. - If you're using MySQL, it needs to define the value `"mysql"` in the `provider` field. Switch around with the tabs in the code block to see examples of both: ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` ```prisma datasource db { provider = "mysql" url = env("DATABASE_URL") } ``` With the `provider` field set, you can go ahead and configure the connection URL inside the `.env` file. Assume the database configuration in your Docker Compose file that you used to deploy your Prisma ORM server looks as follows: ```yml file=docker-compose.yml showLineNumbers PRISMA_CONFIG: | port: 4466 databases: default: connector: postgres host: postgres port: 5432 user: prisma password: prisma ``` Also assume your `endpoint` in `prisma.yml` is configured as follows: ```yml file=prisma.yml endpoint: http://localhost:4466/myproject/dev ``` Based on these connection details, you need to configure the `DATABASE_URL` environment variable inside your `.env` file as follows: ```bash file=.env DATABASE_URL="postgresql://janedoe:randompassword@localhost:5432/prisma?schema=myproject$dev" ``` Note that the `schema` argument is typically composed of your _service name_ and _service stage_ (which are part of the `endpoint` in `prisma.yml`), separated by the `$` character. Sometimes no service name and stage are specified in `prisma.yml`: ```yml file=prisma.yml endpoint: http://localhost:4466/ ``` In that case, the `schema` must be specified as follows: ```bash file=.env DATABASE_URL="postgresql://janedoe:randompassword@localhost:5432/prisma?schema=default$default" ``` Learn more on the [Connection URLs](/orm/reference/connection-urls) page. ## 4. Introspect your database For the purpose of this guide, we'll use the following Prisma 1 data model (select the **SQL** tab below to see what the data model maps to in SQL): ```graphql type User { id: ID! @id email: String @unique name: String! role: Role! @default(value: CUSTOMER) jsonData: Json profile: Profile posts: [Post!]! } type Post { id: ID! @id createdAt: DateTime! @createdAt updatedAt: DateTime! @updatedAt title: String! content: String published: Boolean! @default(value: false) author: User @relation(link: TABLE) categories: [Category!]! } type Profile { id: ID! @id bio: String user: User! @relation(link: INLINE) } type Category { id: ID! @id name: String! posts: [Post!]! } enum Role { ADMIN CUSTOMER } ``` ```sql CREATE TABLE"User" ( id character varying(25) PRIMARY KEY, email text, name text NOT NULL, role text NOT NULL, "jsonData" text ); CREATE UNIQUE INDEX "User_pkey" ON"User"(id text_ops); CREATE UNIQUE INDEX "default$default.User.email._UNIQUE" ON"User"(email text_ops); CREATE TABLE"Post" ( id character varying(25) PRIMARY KEY, title text NOT NULL, published boolean NOT NULL, "createdAt" timestamp(3) without time zone NOT NULL, "updatedAt" timestamp(3) without time zone NOT NULL, content text ); CREATE UNIQUE INDEX "Post_pkey" ON"Post"(id text_ops); CREATE TABLE"Profile" ( id character varying(25) PRIMARY KEY, bio text, user character varying(25) REFERENCES"User"(id) ON DELETE SET NULL ); CREATE UNIQUE INDEX "Profile_pkey" ON"Profile"(id text_ops); CREATE TABLE"Category" ( id character varying(25) PRIMARY KEY, name text NOT NULL ); CREATE UNIQUE INDEX "Category_pkey" ON"Category"(id text_ops); CREATE TABLE"_PostToUser" ( "A" character varying(25) NOT NULL REFERENCES"Post"(id) ON DELETE CASCADE, "B" character varying(25) NOT NULL REFERENCES"User"(id) ON DELETE CASCADE ); CREATE UNIQUE INDEX "_PostToUser_AB_unique" ON"_PostToUser"("A" text_ops,"B" text_ops); CREATE INDEX "_PostToUser_B" ON"_PostToUser"("B" text_ops); CREATE TABLE"_CategoryToPost" ( "A" character varying(25) NOT NULL REFERENCES"Category"(id) ON DELETE CASCADE, "B" character varying(25) NOT NULL REFERENCES"Post"(id) ON DELETE CASCADE ); CREATE UNIQUE INDEX "_CategoryToPost_AB_unique" ON"_CategoryToPost"("A" text_ops,"B" text_ops); CREATE INDEX "_CategoryToPost_B" ON"_CategoryToPost"("B" text_ops); ``` Note that this data model has three [relations](/orm/prisma-schema/data-model/relations): - 1-1: `User` ↔ `Profile` - 1-n: `User` ↔ `Post` (maintained via the `_PostToUser` relation table) - m-n: `Post` ↔ `Category` (maintained via the `_CategoryToPost` relation table) Now you can run Prisma ORM's introspection against your database with the following command: ```terminal copy npx prisma db pull ``` Here's a graphical illustration for what happens when `db pull` is invoked: ![Introspect your database](/img/orm/prisma-db-pull-generate-schema.png) For the above Prisma 1 datamodel, this results in the following Prisma ORM 2 schema (note that the models have been reordered to match the initial order of the Prisma 1 datamodel): ```prisma file=schema.prisma showLineNumbers model User { id String @id @default(cuid()) email String? @unique name String role String jsonData String? Profile Profile[] Post Post[] } model Post { id String @id @default(cuid()) createdAt DateTime updatedAt DateTime title String content String? published Boolean Category Category[] User User[] } model Profile { id String @id @default(cuid()) bio String? user String? @unique User User? @relation(fields: [user], references: [id]) } model Category { id String @id @default(cuid()) name String Post Post[] } ``` While this is already a valid Prisma ORM 2 schema, it lacks a number of _features_ that were part of its Prisma 1 equivalent: - no auto-generated date values for the `createdAt` and `updatedAt` fields on `Post` - no default value for the `role` field on `User` - no default value for the `published` field on `Post` There further are a number of inconsistencies which result in a less idiomatic/ergonomic Prisma Client API: - `User` ↔ `Profile` is a 1-n instead of 1-1 relation - `User` ↔ `Post` is a m-n instead of 1-n relation - relation fields are uppercased (e.g. `Profile` and `Post` on `User`) - the `jsonData` field on `User` is of type `String` instead of `Json` - the `role` field on `User` is of type `String` instead of `Role`, the `enum` definition for role is missing altogether While these inconsistencies don't actually impact the "feature set" you'll have available in your Prisma Client API, they make you lose certain constraints/guarantees that were present before. For example, Prisma ORM now won't guarantee that a `User` is connected to _at most_ one `Profile` because the relation between the tables was recognized as 1-n during introspection, so one `User` record _could_ now get connected to multiple `Profile` records. Another issue is that you can store whatever text for the `jsonData` and `role` fields, regardless of whether it's valid JSON or represents a value of the `Role` enum. To learn more about these inconsistencies check out the [Schema incompatibilities](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql) page. In the following, we'll go through these incompatibilities and fix them one by one using the Prisma schema upgrade CLI. ## 5. Use the Prisma schema upgrade CLI to resolve schema incompatibilities The [Prisma 1 Upgrade CLI](/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade#prisma-1-upgrade-cli) is an interactive tool that helps you upgrading your Prisma schema and ironing out most of the inconsistencies listed above. The Prisma 1 Upgrade CLI works in two major phases: 1. Fix the database schema via plain SQL 1. Add missing attributes to the Prisma ORM 2 schema and other schema fixes During the first phase, it will generate and print a number of SQL statements that you should run against your database to adjust the database schema. You can either run all of the statements or a subset of them before continuing to the second phase. During the second phase, you don't need to do anything manually. The Upgrade CLI will make changes to your Prisma schema by adding certain Prisma ORM-level attributes (like `@default(cuid))` or `@updatedAt`), adjusting the names of relation fields to match the ones from your Prisma 1 datamodel and ensure 1-1-relations that were required on both sides in your Prisma 1 datamodel are also required in the Prisma ORM 2 schema. Note that **you can start over at any time during the process** and go back from the second to the first phase. In this illustration, the green area shows the first phase, the blue area shows the second phase. Note that you can optionally run `prisma db pull` in between the phases to update your Prisma ORM data model: ![Fixing the schema incompatibilities](./images/fix-schema-incompatibilities.png) To use the Upgrade CLI, you can either install it locally in your project, or invoke it once without installation using `npx` as done here: ```terminal copy npx prisma-upgrade prisma1/prisma.yml prisma/schema.prisma ``` The CLI will greet you with the following message: ```no-lines wrap ◮ Welcome to the interactive Prisma Upgrade CLI that helps with the upgrade process from Prisma 1 to Prisma ORM 2. Please read the docs to learn more about the upgrade process: https://pris.ly/d/how-to-upgrade ➤ Goal The Upgrade CLI helps you resolve the schema incompatibilities between Prisma 1 and Prisma ORM 2. Learn more in the docs: https://pris.ly/d/schema-incompatibilities ➤ How it works Throughout the process, you'll need to adjust your database schema by sending SQL statements to it. The SQL statements are provided by the Upgrade CLI. Note that the Upgrade CLI never makes changes to your database, you are in full control over any operations that are executed against it. You can stop and re-run the Upgrade CLI at any time. These are the different steps of the upgrade process: 1. The Upgrade CLI generates SQL commands for you to run on your database. 2. You run the SQL commands against your database. 3. You run the `npx prisma db pull` command again. 4. You run the `npx prisma-upgrade` command again. 5. The Upgrade CLI adjusts the Prisma ORM 2 schema by adding missing attributes. ➤ Note It is recommended that you make a full backup of your existing data before starting the upgrade process. If possible, the migration should be performed in a staging environment before executed against a production environment. ➤ Help If you have any questions or run into any problems along the way, please create an issue at: https://github.com/prisma/prisma1-upgrade/issues Are you ready? [Y/n] ``` Press the Y button, then confirm by hitting RETURN on your keyboard to continue. Once you confirmed, the CLI outputs the SQL statements you should be running against your database: ```no-lines wrap ➤ Adjust your database schema Run the following SQL statements against your database: Fix columns with ENUM data types https://pris.ly/d/schema-incompatibilities#enums-are-represented-as-text-in-database CREATE TYPE "default$default"."Role" AS ENUM ('ADMIN', 'CUSTOMER'); ALTER TABLE "default$default"."User" ALTER COLUMN "role" SET DATA TYPE "default$default"."Role" using "role"::"default$default"."Role"; Add missing `DEFAULT` constraints to the database https://pris.ly/d/schema-incompatibilities#default-values-arent-represented-in-database ALTER TABLE "default$default"."User" ALTER COLUMN "role" SET DEFAULT 'CUSTOMER'; ALTER TABLE "default$default"."Post" ALTER COLUMN "published" SET DEFAULT false; Fix columns with JSON data types https://pris.ly/d/schema-incompatibilities#json-type-is-represented-as-text-in-database ALTER TABLE "default$default"."User" ALTER COLUMN "jsonData" SET DATA TYPE JSONB USING "jsonData"::TEXT::JSONB; Replicate `@createdAt` behavior in Prisma ORM 2 https://pris.ly/d/schema-incompatibilities#createdat-isnt-represented-in-database ALTER TABLE "default$default"."Post" ALTER COLUMN "createdAt" SET DEFAULT CURRENT_TIMESTAMP; Fix 1-1 relations by adding `UNIQUE` constraints https://pris.ly/d/schema-incompatibilities#inline-1-1-relations-are-recognized-as-1-n-missing-unique-constraint ALTER TABLE "default$default"."Profile" ADD UNIQUE ("user"); Migrate IDs from varchar(25) to varchar(30) https://pris.ly/d/schema-incompatibilities#mismatching-cuid-length ALTER TABLE "default$default"."Category" ALTER COLUMN "id" SET DATA TYPE character varying(30); ALTER TABLE "default$default"."Post" ALTER COLUMN "id" SET DATA TYPE character varying(30); ALTER TABLE "default$default"."Profile" ALTER COLUMN "id" SET DATA TYPE character varying(30); ALTER TABLE "default$default"."Profile" ALTER COLUMN "user" SET DATA TYPE character varying(30); ALTER TABLE "default$default"."User" ALTER COLUMN "id" SET DATA TYPE character varying(30); ➤ Breaking changes detected In order to fully optimize your database schema, you'll need to run a few SQL statements that can break your Prisma 1 setup. Note that these changes are optional and if you are upgrading gradually and running Prisma 1 and Prisma ORM 2 side-by-side, you should not perform these changes yet. Instead, you can perform them whenever you are ready to completely remove Prisma 1 from your project. If you are upgrading all at once, you can safely perform these changes now. Learn more in the docs: https://pris.ly/d/how-to-upgrade' ``` > **Note**: If you're seeing the note about breaking changes, you can ignore it for now. We'll discuss it later. The shown SQL statements are categorized into a number of "buckets", all aiming to resolve a certain [schema incompatibility](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql): - Fix columns with ENUM data types - Add missing `DEFAULT` constraints to the database - Fix columns with JSON data types - Replicate `@createdAt` behavior in Prisma 2 - Fix 1-1 relations by adding `UNIQUE` constraints As a next step, you can start sending the SQL statements to your database. Note that all of these changes are non-breaking and you'll be able to continue using Prisma 1 side-by-side with Prisma ORM 2. The next sections cover the different kinds of SQL statements to be sent to your database individually. ### 5.1. Fix the database schema via plain SQL (non-breaking) In this section, we'll walk through the printed SQL statements and run them against the database one by one. ### 5.1.1. Fix columns with ENUM data types The first thing the tool does is help you ensure that `enum` definitions in your Prisma 1 datamodel will be represented as actual `ENUM` types in the underlying database, right now they are represented as plain strings (e.g. as `MEDIUMTEXT` in MySQL). The CLI currently shows the following output: ```no-lines wrap Fix columns with ENUM data types https://pris.ly/d/schema-incompatibilities#enums-are-represented-as-text-in-database CREATE TYPE "default$default"."Role" AS ENUM ('ADMIN', 'CUSTOMER'); ALTER TABLE "default$default"."User" ALTER COLUMN "role" SET DATA TYPE "default$default"."Role" using "role"::"default$default"."Role"; ``` > **⚠️ Warning**: If you are running Prisma 1 and Prisma ORM 2 [side-by-side](/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade#upgrade-strategies), these [SQL statements will break your Prisma 1 setup](https://github.com/prisma/prisma1-upgrade/issues/74). The docs will be updated to reflect this soon. Go ahead and run these statements against your database now. ![Altering columns to use ENUM with SQL](./images/altering-columns-to-use-enum.png) ### 5.1.2. Add missing `DEFAULT` constraints to the database Next, the Upgrade CLI helps you resolve the issue that [default values aren't represented in the database](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql#default-values-arent-represented-in-database) by generating SQL statements that add the respective `DEFAULT` constraints directly to the database. In this case, two `DEFAULT` constraints are missing which are suggested by the tool: ```no-lines wrap Add missing `DEFAULT` constraints to the database https://pris.ly/d/schema-incompatibilities#default-values-arent-represented-in-database ALTER TABLE "default$default"."User" ALTER COLUMN "role" SET DEFAULT 'CUSTOMER'; ALTER TABLE "default$default"."Post" ALTER COLUMN "published" SET DEFAULT false; ``` You can now run these SQL statements against your database either using a command line client or a GUI like Postico: ![Adding missing `DEFAULT` constraints to columns](./images/add-missing-default-constraints-to-columns.png) ### 5.1.3. Fix columns with JSON data types Next, the tool helps you ensure that `Json` fields in your Prisma 1 datamodel will be represented as `JSON` columns in the underlying database, right now they are represented as plain strings (e.g. as `MEDIUMTEXT` in MySQL). Changing the column type to `JSON` will ensure that the field is properly recognized as `Json` during Prisma ORM 2 introspection. The CLI currently shows the following output: ```no-lines wrap Fix columns with JSON data types https://pris.ly/d/schema-incompatibilities#json-type-is-represented-as-text-in-database ALTER TABLE "default$default"."User" ALTER COLUMN "jsonData" TYPE JSON USING "jsonData"::json; ``` > **⚠️ Warning**: If you are running Prisma 1 and Prisma ORM 2 [side-by-side](/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade#upgrade-strategies), these [SQL statements will break your Prisma 1 setup](https://github.com/prisma/prisma1-upgrade/issues/73). The docs will be updated to reflect this soon. You can now run these SQL statements against your database either using a command line client or a GUI like Postico: ![Adding missing `DEFAULT` constraints to columns](./images/fix-columns-with-json-data-types.png) ### 5.1.4. Replicate `@createdAt` behavior in Prisma ORM 2 The next thing the tools does is help you resolve the issue that the behavior of [`@createdAt` isn't represented in database](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql#default-values-arent-represented-in-database) The CLI currently shows the following output: ```no-lines wrap Replicate `@createdAt` behavior in Prisma ORM 2.0 https://pris.ly/d/schema-incompatibilities#createdat-isnt-represented-in-database ALTER TABLE "default$default"."Post" ALTER COLUMN "createdAt" SET DEFAULT CURRENT_TIMESTAMP; ``` You can now run these SQL statements against your database either using a command line client or a GUI like Postico: ![Running an SQL command to alter a column](./images/run-sql-command-to-alter-column.png) ### 5.1.5. Fix 1-1 relations by adding `UNIQUE` constraints Now, the tool will help you [turn the current 1-n relation between `User` ↔ `Profile` back into a 1-1 relation](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql#inline-1-1-relations-are-recognized-as-1-n-missing-unique-constraint) by adding a `UNIQUE` constraint to the foreign key column called `user` (named after the relation field in the Prisma 1 datamodel) in the database. The CLI currently shows the following output: ```no-lines wrap Fix 1-1 relations by adding `UNIQUE` constraints https://pris.ly/d/schema-incompatibilities#inline-1-1-relations-are-recognized-as-1-n-missing-unique-constraint ALTER TABLE "default$default"."Profile" ADD UNIQUE ("user"); ``` You can now run these SQL statements against your database either using a command line client or a GUI like Postico: ![Running an SQL command to alter a column](./images/run-sql-command-to-alter-column.png) ### 5.1.6. Fix mismatch of CUID length > **Note**: These SQL statements will keep appearing in the Upgrade CLI even after you have changed the column types in the underlying database. This is a currently a limitation in the Upgrade CLI. Finally, the tool will help you [turn the current ID columns of type `VARCHAR(25)` into `VARCHAR(30)`](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql#mismatching-cuid-length) by adding a `UNIQUE` constraint to the foreign key column called `user` (named after the relation field in the Prisma 1 datamodel) in the database. The CLI currently shows the following output: ```no-lines wrap wrap Migrate IDs from varchar(25) to varchar(30) https://pris.ly/d/schema-incompatibilities#mismatching-cuid-length ALTER TABLE "default$default"."Category" ALTER COLUMN "id" SET DATA TYPE character varying(30); ALTER TABLE "default$default"."Post" ALTER COLUMN "id" SET DATA TYPE character varying(30); ALTER TABLE "default$default"."Profile" ALTER COLUMN "id" SET DATA TYPE character varying(30); ALTER TABLE "default$default"."Profile" ALTER COLUMN "user" SET DATA TYPE character varying(30); ALTER TABLE "default$default"."User" ALTER COLUMN "id" SET DATA TYPE character varying(30); ``` You can now run these SQL statements against your database either using a command line client or a GUI like Postico: ![Running an SQL command to alter a column](./images/run-sql-command-to-alter-column.png) ### 5.1.7. Breaking changes detected In case the Upgrade CLI has printed a note about breaking changes, your database schema needs some adjustments that will break Prisma 1 compatibility in order to be fully optimized. If there are no breaking changes detected, you can [skip forward to section 5.2](#52-re-introspect-your-database-to-update-your-prisma-schema) Depending on your [upgrade strategy](/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade#upgrade-strategies), you can either perform these changes now or skip to the next phase of the Upgrade CLI: - If you are following the gradual side-by-side upgrade strategy, do not perform these changes yet since they will break your Prisma 1 setup. In that case, you can continue to the next phase of the Upgrade CLI by typing n and hitting RETURN. - If you are following the all at once upgrade strategy, you can perform these changes now. In that case, continue by typing Y and hitting RETURN. ### 5.2. Fix the database schema via plain SQL (breaking) In this section, you'll resolve the schema incompatibilities that are breaking your Prisma 1 setup. Do not perform these changes if you are still running Prisma 1 in your project! ### 5.2.1. Fix incorrect m-n relations Now, the Upgrade CLI helps you fix all 1-1 and 1-n relations that Prisma 1 represents with relation tables and that [currently only exist as m-n relations](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql#all-non-inline-relations-are-recognized-as-m-n) in your new Prisma ORM 2 schema. Concretely, this is the case for the `User` ↔ `Post` relation which currently is defined as m-n but _should_ really be a 1-n relation. To fix this, you'll need to perform the following migration: 1. Create a new foreign key column on `Post` to link directly to the `User` table. 1. Migrate the foreign key values from the relation table into the new foreign key column on `Post`. 1. Delete the relation table. These instructions are now printed by the CLI: ```no-lines wrap ➤ Adjust your database schema Run the following SQL statements against your database: Fix one-to-many table relations https://pris.ly/d/schema-incompatibilities#all-non-inline-relations-are-recognized-as-m-n ALTER TABLE "default$default"."Post" ADD COLUMN "authorId" character varying(25) ; ALTER TABLE "default$default"."Post" ADD CONSTRAINT "author" FOREIGN KEY ("authorId") REFERENCES "default$default"."User"("id"); UPDATE "default$default"."Post" SET "authorId" = "default$default"."_PostToUser"."B" FROM "default$default"."_PostToUser" WHERE "default$default"."_PostToUser"."A" = "default$default"."Post"."id"; DROP TABLE "default$default"."_PostToUser"; ➤ Next Steps After you executed one or more of the previous SQL statements against your database, please run the following two commands to refresh your Prisma ORM 2 schema and check the changes. 1. Run `npx prisma db pull` again to refresh your Prisma ORM 2 schema. 2. Run `npx prisma-upgrade` again. If you can't or don't want to execute the remaining SQL statements right now, you can skip to the last step where the Upgrade CLI adds missing attributes to your Prisma ORM 2 schema that are not picked up by introspection. Skip to the last step? [Y/n]? ``` For this fix, you'll need to run three SQL statements: 1. Create new column `authorId` on the `Post` table. This column should be a _foreign key_ that references the `id` field of the `User` table: ```sql no-lines ALTER TABLE `Post` ADD COLUMN `authorId` VARCHAR(25); ALTER TABLE `Post` ADD FOREIGN KEY (`authorId`) REFERENCES `User` (`id`); ``` 1. Write a SQL query that reads all the rows from the `_PostToUser` relation table and for each row: 1. Finds the respective `Post` record by looking up the value from column `A` 1. Inserts the value from column `B` as the value for `authorId` into that `Post` record ```sql no-lines UPDATE Post, _PostToUser SET Post.authorId = _PostToUser.B WHERE Post.id = _PostToUser.A ``` 1. Delete the `_PostToUser` relation table ```sql no-lines DROP TABLE `_PostToUser`; ``` ![Fixing incorrect m-n relations with SQL](./images/fix-incorrect-m-n-relations-sql.png) After these commands, the user ID values of the records from column `B` of the relation table are migrated to the new `authorId` column. ### 5.2. Re-introspect your database to update your Prisma schema At this point, you've resolved the schema incompatibilities with the Upgrade CLI. You can now exit the Upgrade CLI for now by typing n and hitting RETURN. In this section, you'll update your Prisma schema with another introspection round. This time, the previous flaws of the Prisma schema will be resolved because the database schema has been adjusted: ```terminal copy npx prisma db pull ``` This time, the resulting Prisma schema looks as follows: ```prisma file=schema.prisma showLineNumbers model User { id String @id name String email String? @unique jsonData Json? role Role @default(CUSTOMER) Post Post[] Profile Profile? } model Post { id String @id createdAt DateTime @default(now()) updatedAt DateTime title String content String? published Boolean @default(false) authorId String? User User? @relation(fields: [authorId], references: [id]) Category Category[] @relation(references: [id]) } model Category { id String @id name String Post Post[] @relation(references: [id]) } model Profile { bio String? id String @id user String? @unique User User? @relation(fields: [user], references: [id]) } enum Role { ADMIN CUSTOMER } ``` This schema has most issues resolved, but it still lacks the following: ### 5.2. Add missing attributes to the Prisma 2 schema and other schema fixes The CLI now prints the following: ``` wrap ➤ What happens next As a last step, some final adjustments will be made to your Prisma ORM 2 schema to carry over some Prisma ORM-level attributes that aren't picked up by introspection. As a last step, some final adjustments will be made to your Prisma ORM 2.0 schema to carry over some Prisma ORM-level attributes that aren't picked up by introspection. Warning Your current Prisma ORM 2.0 schema will be overwritten, so please make sure you have a backup! Are you ready? [Y/n] ``` At this point, you either ran all the SQL statement that were printed by the CLI or you skipped some of them. Either way, you can now move on the last step and let the Upgrade CLI add the missing Prisma ORM 2 attributes. Typically these are the following: - `@default(cuid())` for your `@id` fields - `@updatedAt` for any fields that were using this attribute in Prisma 1 - `@map` and `@@map` as replacements for `@db` and `@@db` from Prisma 1 In that step, the Upgrade CLI also fixes other issues that occurred in the transition to Prisma ORM 2: - it makes sure that 1-1-relations that were required on both sides in Prisma 1 are also required in your Prisma ORM 2 schema - it renames relation fields to the same names they had in your Prisma 1 datamodel ([coming soon](https://github.com/prisma/prisma1-upgrade/issues/25)) To apply these changes, you can re-run the Upgrade CLI: ```terminal copy npx prisma-upgrade prisma1/prisma.yml prisma/schema.prisma ``` If you did not resolve all schema incompatibilities, the Upgrade CLI now prints the remaining SQL statements (as well as the ones for migrating IDs). You can just ignore them at this point and continue to the last step by continuously typing Y and hitting RETURN when prompted. If you did resolve all schema incompatibilities, no SQL statements will be printed and the Upgrade CLI only outputs the following: ```no-lines wrap $ npx prisma-upgrade prisma1/prisma.yml prisma/schema.prisma ➤ Next Steps After you executed one or more of the previous SQL statements against your database, please run the following two commands to refresh your Prisma ORM 2 schema and check the changes. 1. Run `npx prisma db pull` again to refresh your Prisma ORM 2 schema. 2. Run `npx prisma-upgrade` again. If you can't or don't want to execute the remaining SQL statements right now, you can skip to the last step where the Upgrade CLI adds missing attributes to your Prisma ORM 2 schema that are not picked up by introspection. Skip to the last step? [Y/n]? ``` One more time, type Y and hit RETURN to confirm. The final prompt of the Upgrade CLI now asks you to confirm the above mentioned changes it will make to your Prisma schema: ```no-lines wrap ➤ What happens next As a last step, some final adjustments will be made to your Prisma ORM 2 schema to carry over some Prisma ORM-level attributes that aren't picked up by introspection. As a last step, some final adjustments will be made to your Prisma ORM 2.0 schema to carry over some Prisma ORM-level attributes that aren't picked up by introspection. Warning Your current Prisma ORM 2.0 schema will be overwritten, so please make sure you have a backup! Are you ready? [Y/n] ``` One last time, type Y and hit RETURN to confirm. This is the final output of the Upgrade CLI: ```no-lines Updating prisma/schema.prisma... Done updating prisma/schema.prisma! ✔ Congratulations, you're all set! ➤ Note If you didn't execute all generated SQL commands against your database, you can re-run the Upgrade CLI at any time. Note that the Upgrade CLI doesn't resolve all of the schema incompatibilities between Prisma 1 and Prisma ORM 2. If you want to resolve the remaining ones, you can do so manually by following this guide: https://pris.ly/d/upgrading-the-prisma-layer ➤ Next steps Otherwise you can continue your upgrade process by installing Prisma Client 2: npm install @prisma/client You can find guides for different upgrade scenarios in the docs: https://pris.ly/d/upgrade-from-prisma-1 ``` ### 5.3. Final result The final version of the Prisma schema should look as follows: ```prisma file=schema.prisma showLineNumbers model User { id String @id @default(cuid()) name String email String? @unique jsonData Json? role Role @default(CUSTOMER) Post Post[] Profile Profile? } model Post { id String @id @default(cuid()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String content String? published Boolean @default(false) authorId String? User User? @relation(fields: [authorId], references: [id]) Category Category[] @relation(references: [id]) } model Profile { id String @id @default(cuid()) bio String? user String? @unique User User? @relation(fields: [user], references: [id]) } model Category { id String @id @default(cuid()) name String Post Post[] @relation(references: [id]) } enum Role { ADMIN CUSTOMER } ``` ### 5.4. Rename relation fields One thing you'll notice with this version of the Prisma ORM 2 schema is that all [relation fields](/orm/prisma-schema/data-model/relations#relation-fields) are named after their respective models, e.g: ```prisma file=schema.prisma showLineNumbers model User { Post Post[] Profile Profile? } model Post { User User? @relation(fields: [authorId], references: [id]) Category Category[] @relation(references: [id]) } model Profile { User User? @relation(fields: [user], references: [id]) } model Category { Post Post[] @relation(references: [id]) } ``` This is not ideal and you can in fact manually rename all of them to their previous versions! Because all relation fields are _virtual_, meaning they don't _manifest_ in the database, you can name them whatever you like. In this case, all relation fields are lowercased and sometimes pluralized. Here's what they look like after the rename: ```prisma file=schema.prisma showLineNumbers model User { posts Post[] profile Profile? } model Post { author User? @relation(fields: [authorId], references: [id]) categories Category[] @relation(references: [id]) } model Profile { user String? @unique owner User? @relation(fields: [user], references: [id]) } model Category { posts Post[] @relation(references: [id]) } ``` > **Note**: For the 1-1-relation between `User` and `Profile` it was not possible to set the old name `user` for the relation field. This is because there'd be a naming conflict with the already existing [relation scalar](/orm/prisma-schema/data-model/relations#annotated-relation-fields) field that holds the foreign key. In that case, you can choose a different name or alternatively rename the foreign key column directly in the database via SQL. ### 5.5. Resolving remaining schema incompatibilities There are a few schema incompatibilities that were not yet resolved by the Upgrade CLI. At this point you still haven't fixed [scalar lists](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql#scalar-lists-arrays-are-maintained-with-extra-table). You can find the recommended workarounds for this and others on the [Schema incompatibilities](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql) page. ## 6. Install and generate Prisma Client Now that you have your Prisma ORM 2 schema ready, you can install Prisma Client with the following command: ```terminal copy npm install @prisma/client ``` ## 7. Next steps Congratulations, you have now upgraded your Prisma ORM layer to Prisma ORM 2! From here on, you can move on to update your application code using one of the following guides: - [Old to new Nexus](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-nexus-prisma-to-nexus): Choose this guide if you're currently running Prisma 1 with GraphQL Nexus. - [prisma-binding to Nexus](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-prisma-binding-to-nexus): Choose this guide if you're currently running Prisma 1 with `prisma-binding` and want to upgrade to [Nexus](https://nexusjs.org/) (and TypeScript). - [prisma-binding to SDL-first](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-prisma-binding-to-sdl-first): Choose this guide if you're currently running Prisma 1 with `prisma-binding` and want to upgrade to an [SDL-first](https://www.prisma.io/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3) GraphQL server. - [REST API](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-a-rest-api): Choose this guide if you're currently running Prisma 1 using Prisma Client 1 and are building a REST API. ## Bonus: Prisma Client API comparison This section contains a high-level and side-by-side comparison of the Prisma Client APIs of Prisma 1 and Prisma ORM 2. For more details about the new Prisma Client API, you can explore the [Prisma Client](/orm/prisma-client) docs. ### Reading single records ```ts const user = await prisma.user({ id: 1 }) ``` ```ts await prisma.user.findUnique({ where: { id: 1 }, }) ``` ### Reading lists of records ```ts const user = await prisma.users() ``` ```ts await prisma.user.findMany() ``` ### Filtering lists ```ts const users = await prisma.users({ where: { name: 'Alice', }, }) ``` ```ts await prisma.user.findMany({ where: { name: 'Alice', }, }) ``` ### Paginating lists ```ts const posts = await prisma.posts({ skip: 5, first: 10, }) ``` ```ts await prisma.user.findMany({ skip: 5, take: 10, }) ``` > **Note**: You can learn more about the new pagination API in the respective [release notes](https://github.com/prisma/prisma/releases/tag/2.0.0-beta.7) or the [Pagination](/orm/prisma-client/queries/pagination) page in the docs. ### Sorting lists ```ts await prisma.posts({ orderBy: 'title_ASC', }) ``` ```ts await prisma.posts({ orderBy: { title: 'asc', }, }) ``` ### Creating records ```ts await prisma.createUser({ name: 'Alice', }) ``` ```ts await prisma.user.create({ data: { name: 'Alice', }, }) ``` ### Updating records ```ts await prisma.updateUser({ where: { id: 1 }, data: { name: 'James', email: 'james@prisma.io', }, }) ``` ```ts await prisma.user.update({ where: { id: 1 }, data: { name: 'James', email: 'james@prisma.io', }, }) ``` ### Deleting records ```ts await prisma.deleteUser({ id: 1 }) ``` ```ts await prisma.user.delete({ where: { id: 1 }, }) ``` ### Selecting fields & loading relations In Prisma 1, the only ways to select specific fields and/or load relations of an object was by using the string-based `$fragment` and `$graphql` functions. With Prisma ORM 2, this is now done in a clean and type-safe manner using [`select`](/orm/prisma-client/queries/select-fields#select-specific-fields) and [`include`](/orm/prisma-client/queries/select-fields#return-nested-objects-by-selecting-relation-fields). Another benefit of this approach is that you can use `select` and `include` on _any_ Prisma Client query, e.g. `findUnique()`, `findMany`, `create`, `update`, `delete`, ... ```ts await prisma.user({ id: 1 }).$fragment(` fragment NameAndEmail on User { id email }` `) ``` ```ts await prisma.user.findUnique({ where: { id: 1 }, select: { id: true, email: true, }, }) ``` As an example, creating a new record and only retrieving the `id` in the returned object was not possible in Prisma 1. With Prisma ORM 2 you can achieve this as follows: ```ts await prisma.user.create({ data: { name: 'Alice', }, select: { id: true, }, }) ``` --- # Old to new Nexus URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-nexus-prisma-to-nexus ## Overview :::info This guide is not fully up-to-date as it currently uses the [deprecated](https://github.com/graphql-nexus/nexus-plugin-prisma/issues/1039) version of the [`nexus-plugin-prisma`](https://github.com/graphql-nexus/nexus-plugin-prisma). While this is still functional, it is recommended to use the new [`nexus-prisma`](https://github.com/graphql-nexus/nexus-prisma/) library or an alternative code-first GraphQL library like [Pothos](https://pothos-graphql.dev/) going forward. If you have any questions, feel free to share them on our [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=intro_text). ::: This upgrade guide describes how to upgrade a project that's based on [Prisma 1](https://github.com/prisma/prisma1) and uses [`nexus`](https://www.npmjs.com/package/nexus) (< v0.12.0) or [`@nexus/schema`](https://github.com/graphql-nexus/nexus) together with [`nexus-prisma`](https://www.npmjs.com/package/nexus-prisma) (< v4.0.0) to implement a GraphQL server. The code will be upgraded to the latest version of `@nexus/schema`. Further, the `nexus-prisma` package will be replaced with the new [`nexus-plugin-prisma`](https://github.com/graphql-nexus/nexus-plugin-prisma). The guide assumes that you already went through the [guide for upgrading the Prisma ORM layer](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-the-prisma-layer-postgresql). This means you already: - installed the Prisma ORM 2 CLI - created your Prisma ORM 2 schema - introspected your database and resolved potential [schema incompatibilities](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql) - installed and generated Prisma Client The guide further assumes that you have a file setup that looks similar to this: ``` . ├── README.md ├── package.json ├── prisma │ └── schema.prisma ├── prisma1 │ ├── datamodel.prisma │ └── prisma.yml └── src ├── generated │ ├── nexus-prisma │ ├── nexus.ts │ ├── prisma-client │ └── schema.graphql ├── types.ts └── index.ts ``` The important parts are: - A folder called with `prisma` with your Prisma ORM 2 schema - A folder called `src` with your application code If this is not what your project structure looks like, you'll need to adjust the instructions in the guide to match your own setup. ## 1. Upgrade Nexus dependencies To get started, you can remove the old Nexus and Prisma 1 dependencies: ```copy npm uninstall nexus nexus-prisma prisma-client-lib prisma1 ``` Then, you can install the latest `@nexus/schema` dependency in your project: ```copy npm install @nexus/schema ``` Next, install the Prisma ORM plugin for Nexus which will allow you to expose Prisma ORM models in your GraphQL API (this is the new equivalent of the former `nexus-prisma` package): ```copy npm install nexus-plugin-prisma ``` The `nexus-plugin-prisma` dependency bundles all required Prisma ORM dependencies. You should therefore remove the dependencies that you added installed when you upgraded the Prisma ORM layer of your app: ```copy npm uninstall @prisma/cli @prisma/client ``` Note however that you can still invoke the Prisma ORM 2 CLI with the familiar command: ```copy npx prisma -v ``` > **Note**: If you see the output of the Prisma 1 CLI when running `npx prisma -v`, be sure to delete your `node_modules` folder and re-run `npm install`. ## 2. Update the configuration of Nexus and Prisma ORM To get started, you can remove the old imports that are not needed any more with your new setup: ```ts line-number highlight=1-3;delete //delete-start import { makePrismaSchema, prismaObjectType } from 'nexus-prisma' import datamodelInfo from './generated/nexus-prisma' import { prisma } from './generated/prisma-client' //delete-end ``` Instead, you now import the following into your application: ```ts line-number highlight=1-3;add //add-start import { nexusSchemaPrisma } from 'nexus-plugin-prisma/schema' import { objectType, makeSchema, queryType, mutationType } from '@nexus/schema' import { PrismaClient } from '@prisma/client' //add-end ``` Next you need to adjust the code where you currently create your `GraphQLSchema`, most likely this is currently happening via the `makePrismaSchema` function in your code. Since this function was imported from the removed `nexus-prisma` package, you'll need to replace it with the `makeSchema` function from the `@nexus/schema` package. The way how the Prisma ORM plugin for Nexus is used also changes in the latest version. Here's an example for such a configuration: ```ts file=./src/index.ts line-number highlight=2,12-14;add|1,8-11;delete showLineNumbers //delete-next-line const schema = makePrismaSchema({ //add-next-line const schema = makeSchema({ // Provide all the GraphQL types we've implemented types: [Query, Mutation, UserUniqueInput, User, Post, Category, Profile], // Configure the interface to Prisma //delete-start prisma: { datamodelInfo, client: prisma, }, //delete-end //add-start plugins: [nexusSchemaPrisma({ experimentalCRUD: true, })], //add-end // Specify where Nexus should put the generated files outputs: { schema: path.join(__dirname, './generated/schema.graphql'), typegen: path.join(__dirname, './generated/nexus.ts'), }, // Configure nullability of input arguments: All arguments are non-nullable by default nonNullDefaults: { input: false, output: false, }, // Configure automatic type resolution for the TS representations of the associated types typegenAutoConfig: { sources: [ { source: path.join(__dirname, './types.ts'), alias: 'types', }, ], contextType: 'types.Context', }, }) ``` If you previously typed the GraphQL `context` object that's passed through your resolver chain, you need to adjust the type like so: ```ts file=./src/types.ts highlight=2,6;add|1,5;delete showLineNumbers //delete-next-line import { Prisma } from './generated/prisma-client' //add-next-line import { PrismaClient } from '@prisma/client' export interface Context { //delete-next-line prisma: Prisma //add-next-line prisma: PrismaClient } ``` ## 3. Migrate your GraphQL types Here's a quick overview of the main differences between the two approaches of creating GraphQL types with the latest versions of `@nexus/schema` and `nexus-plugin-prisma`. - The `prismaObjectType` function is not available any more, all types are created with Nexus' `objectType` function. - To expose Prisma models via Nexus, you can use the `t.model` property which is added to the `t` argument that's passed into Nexus' `definition` functions. `t.model` gives you access to the properties of a Prisma model and lets you expose them. - Exposing CRUD operations for Prisma models via Nexus follows a similar approach. These are exposed via `t.crud` in the `definition` functions of your `queryType` and `mutationType` types. ### 3.1. Migrating the `Post` type #### Type definition with the previous `nexus-prisma` package In the sample app, the `User` type is defined as follows: ```ts const User = prismaObjectType({ name: 'User', definition(t) { t.prismaFields([ 'id', 'name', 'email', 'jsonData', 'role' { name: 'posts', args: [], // remove the arguments from the `posts` field of the `User` type in the Prisma schema }, ]) }, }) ``` #### Type definition with the latest version of `@nexus/schema` and the `nexus-plugin-prisma` With the latest version of `@nexus/schema`, you can now access the `objectType` function on your main `schema` instance and expose all fields from the Prisma model like so: ```ts const User = objectType({ name: 'User', definition(t) { t.model.id() t.model.name() t.model.email() t.model.jsonData() t.model.role() t.model.posts({ pagination: false, ordering: false, filtering: false, }) t.model.profile() }, }) ``` Note that `t.model` looks at the `name` attribute in the object that's passed as an argument to the `objectType` function and matches it against the models in your Prisma schema. In this case, it's matched against the `User` model. Therefore, `t.model` exposes functions that are named after the fields of the `User` model. At this point, you might see errors on the relation fields `posts` and `profile`, e.g.: ```bash highlight=1;delete //delete-next-line Missing type Post, did you forget to import a type to the root query? ``` This is because you didn't add the `Post` and `Profile` types to the GraphQL schema yet, the errors will go away once these types are part of the GraphQL schema as well! ### 3.2. Migrating the `Post` type #### Type definition with the previous `nexus-prisma` package In the sample app, the `Post` type is defined as follows: ```ts const Post = prismaObjectType({ name: 'Post', definition(t) { t.prismaFields(['*']) }, }) ``` The asterisk in `prismaFields` means that _all_ Prisma fields are exposed. #### Type definition with the latest version of `@nexus/schema` and the `nexus-plugin-prisma` With the latest version of `@nexus/schema`, you need to expose all fields explicitly, there's no option to just expose everything from a Prisma model. Therefore, the new definition of `Post` must explicitly list all its fields: ```ts const Post = objectType({ name: 'Post', definition(t) { t.model.id() t.model.title() t.model.content() t.model.published() t.model.author() t.model.categories() }, }) ``` Note that `t.model` looks at the `name` attribute and matches it against the models in your Prisma schema. In this case, it's matched against the `Post` model. Therefore, `t.model` exposes functions that are named after the fields of the `Post` model. ### 3.3. Migrating the `Profile` type #### Type definition with the previous `nexus-prisma` package In the sample app, the `Profile` type is defined as follows: ```ts const Profile = prismaObjectType({ name: 'Profile', definition(t) { t.prismaFields(['*']) }, }) ``` The asterisk in `prismaFields` means that _all_ Prisma fields are exposed. #### Type definition with the latest version of `@nexus/schema` and the `nexus-plugin-prisma` With the latest version of `@nexus/schema`, you need to expose all fields explicitly, there's no option to just expose everything from a Prisma model. Therefore, the new definition of `Profile` must explicitly list all its fields: ```ts const Profile = objectType({ name: 'Profile', definition(t) { t.model.id() t.model.bio() t.model.user() t.model.userId() }, }) ``` Note that `t.model` looks at the `name` attribute and matches it against the models in your Prisma schema. In this case, it's matched against the `Profile` model. Therefore, `t.model` exposes functions that are named after the fields of the `Profile` model. ### 3.4. Migrating the `Category` type #### Type definition with the previous `nexus-prisma` package In the sample app, the `Category` type is defined as follows: ```ts const Category = prismaObjectType({ name: 'Category', definition(t) { t.prismaFields(['*']) }, }) ``` The asterisk in `prismaFields` means that _all_ Prisma ORM fields are exposed. #### Type definition with the latest version of `@nexus/schema` and the `nexus-plugin-prisma` With the latest version of `@nexus/schema`, you need to expose all fields explicitly, there's no option to just expose everything from a Prisma model. Therefore, the new definition of `Category` must explicitly list all its fields: ```ts const Category = objectType({ name: 'Category', definition(t) { t.model.id() t.model.name() t.model.posts({ pagination: true, ordering: true, filtering: true, }) }, }) ``` Note that `t.model` looks at the `name` attribute and matches it against the models in your Prisma schema. In this case, it's matched against the `Category` model. Therefore, `t.model` exposes functions that are named after the fields of the `Category` model. ## 4. Migrate GraphQL operations As a next step, you can start migrating all the GraphQL _queries_ and _mutations_ from the "previous" GraphQL API to the new one. For this guide, the following sample GraphQL operations will be used: ```graphql input UserUniqueInput { id: String email: String } type Query { posts(searchString: String): [Post!]! user(userUniqueInput: UserUniqueInput!): User users(where: UserWhereInput, orderBy: Enumerable, skip: Int, after: String, before: String, first: Int, last: Int): [User]! } type Mutation { createUser(data: UserCreateInput!): User! createDraft(title: String!, content: String, authorId: ID!): Post updateBio(userUniqueInput: UserUniqueInput!, bio: String!): User addPostToCategories(postId: String!, categoryIds: [String!]!): Post } ``` ### 4.1. Migrate GraphQL queries In this section, you'll migrate all GraphQL _queries_ from the previous version of `nexus` and `nexus-prisma` to the latest version of `@nexus/schema` and the `nexus-plugin-prisma`. #### 4.1.1. Migrate the `users` query In our sample API, the `users` query from the sample GraphQL schema is implemented as follows. ```ts const Query = prismaObjectType({ name: 'Query', definition(t) { t.prismaFields(['users']) }, }) ``` To get the same behavior with the new Nexus, you need to call the `users` function on `t.crud`: ```ts schema.queryType({ definition(t) { t.crud.users({ filtering: true, ordering: true, pagination: true, }) }, }) ``` Recall that the `crud` property is added to `t` by the `nexus-plugin-prisma` (using the same mechanism as for `t.model`). #### 4.1.2. Migrate the `posts(searchString: String): [Post!]!` query In the sample API, the `posts` query is implemented as follows: ```ts queryType({ definition(t) { t.list.field('posts', { type: 'Post', args: { searchString: stringArg({ nullable: true }), }, resolve: (parent, { searchString }, context) => { return context.prisma.posts({ where: { OR: [ { title_contains: searchString }, { content_contains: searchString }, ], }, }) }, }) }, }) ``` The only thing that needs to be updated for this query is the call to Prisma ORM since the new Prisma Client API looks a bit different from the one used in Prisma 1. ```ts line-number highlight=6,9,12,13;normal queryType({ definition(t) { t.list.field('posts', { type: 'Post', args: { searchString: stringArg({ nullable: true }), }, resolve: (parent, { searchString }, context) => { return context.prisma.post.findMany({ where: { OR: [ { title: { contains: searchString } }, { content: { contains: searchString } }, ], }, }) }, }) }, }) ``` Notice that the `db` object is automatically attached to the `context` by the `nexus-plugin-prisma`. It represents an instance of your `PrismaClient` which enables you to send queries to your database inside your resolvers. #### 4.1.3. Migrate the `user(uniqueInput: UserUniqueInput): User` query In the sample API, the `user` query is implemented as follows: ```ts inputObjectType({ name: 'UserUniqueInput', definition(t) { t.string('id') t.string('email') }, }) queryType({ definition(t) { t.field('user', { type: 'User', args: { userUniqueInput: schema.arg({ type: 'UserUniqueInput', nullable: false, }), }, resolve: (_, args, context) => { return context.prisma.user({ id: args.userUniqueInput?.id, email: args.userUniqueInput?.email, }) }, }) }, }) ``` You now need to adjust the call to your `prisma` instance since the new Prisma Client API looks a bit different from the one used in Prisma 1. ```ts line-number highlight=6,12-17;normal const Query = queryType({ definition(t) { t.field('user', { type: 'User', args: { //highlight-next-line userUniqueInput: arg({ type: 'UserUniqueInput', nullable: false, }), }, resolve: (_, args, context) => { //highlight-start return context.prisma.user.findUnique({ where: { id: args.userUniqueInput?.id, email: args.userUniqueInput?.email, }, }) //highlight-end }, }) }, }) ``` ### 4.2. Migrate GraphQL mutations In this section, you'll migrate the GraphQL mutations from the sample schema to the latest versions of `@nexus/schema` and the `nexus-plugin-prisma`. #### 4.2.1. Migrate the `createUser` mutation In our sample API, the `createUser` mutation from the sample GraphQL schema is implemented as follows. ```ts const Mutation = prismaObjectType({ name: 'Mutation', definition(t) { t.prismaFields(['createUser']) }, }) ``` To get the same behavior with the latest versions of `@nexus/schema` and the `nexus-plugin-prisma`, you need to call the `createOneUser` function on `t.crud` and pass an `alias` in order to rename the field in your GraphQL schema to `createUser` (otherwise it would be called `createOneUser`, after the function that's used): ```ts const Query = queryType({ definition(t) { t.crud.createOneUser({ alias: 'createUser', }) }, }) ``` Recall that the `crud` property is added to `t` by the `nexus-plugin-prisma` (using the same mechanism as for `t.model`). #### 4.2.2. Migrate the `createDraft(title: String!, content: String, authorId: String!): Post!` query In the sample app, the `createDraft` mutation implemented as follows. ```ts line-number mutationType({ definition(t) { t.field('createDraft', { type: 'Post', args: { title: stringArg({ nullable: false }), content: stringArg(), authorId: stringArg({ nullable: false }), }, resolve: (_, args, context) => { return context.prisma.createPost({ title: args.title, content: args.content, author: { connect: { id: args.authorId }, }, }) }, }) }, }) ``` You now need to adjust the call to your `prisma` instance since the new Prisma Client API looks a bit different from the one used in Prisma 1. ```ts line-number highlight=11-19;normal const Mutation = mutationType({ definition(t) { t.field('createDraft', { type: 'Post', args: { title: stringArg({ nullable: false }), content: stringArg(), authorId: stringArg({ nullable: false }), }, resolve: (_, args, context) => { //highlight-start return context.prisma.post.create({ data: { title: args.title, content: args.content, author: { connect: { id: args.authorId }, }, }, }) //highlight-end }, }) }, }) ``` #### 4.2.3. Migrate the `updateBio(bio: String, userUniqueInput: UserUniqueInput!): User` mutation In the sample API, the `updateBio` mutation is defined and implemented as follows. ```ts mutationType({ definition(t) { t.field('updateBio', { type: 'User', args: { userUniqueInput: arg({ type: 'UserUniqueInput', nullable: false, }), bio: stringArg(), }, resolve: (_, args, context) => { return context.prisma.updateUser({ where: { id: args.userUniqueInput?.id, email: args.userUniqueInput?.email, }, data: { profile: { create: { bio: args.bio }, }, }, }) }, }) }, }) ``` You now need to adjust the call to your `prisma` instance since the new Prisma Client API looks a bit different from the one used in Prisma 1. ```ts highlight=13-23;normal const Mutation = mutationType({ definition(t) { t.field('updateBio', { type: 'User', args: { userUniqueInput: arg({ type: 'UserUniqueInput', nullable: false, }), bio: stringArg(), }, resolve: (_, args, context) => { //highlight-start return context.prisma.user.update({ where: { id: args.userUniqueInput?.id, email: args.userUniqueInput?.email, }, data: { profile: { create: { bio: args.bio }, }, }, }) //highlight-end }, }) }, }) ``` #### 4.2.4. Migrate the `addPostToCategories(postId: String!, categoryIds: [String!]!): Post` mutation In the sample API, the `addPostToCategories` mutation is defined and implemented as follows. ```ts line-number mutationType({ definition(t) { t.field('addPostToCategories', { type: 'Post', args: { postId: stringArg({ nullable: false }), categoryIds: stringArg({ list: true, nullable: false, }), }, resolve: (_, args, context) => { const ids = args.categoryIds.map((id) => ({ id })) return context.prisma.updatePost({ where: { id: args.postId, }, data: { categories: { connect: ids }, }, }) }, }) }, }) ``` You now need to adjust the call to your `prisma` instance since the new Prisma Client API looks a bit different from the one used in Prisma 1. ```ts line-number highlight=14-21;normal const Mutation = mutationType({ definition(t) { t.field('addPostToCategories', { type: 'Post', args: { postId: stringArg({ nullable: false }), categoryIds: stringArg({ list: true, nullable: false, }), }, resolve: (_, args, context) => { const ids = args.categoryIds.map((id) => ({ id })) //highlight-start return context.prisma.post.update({ where: { id: args.postId, }, data: { categories: { connect: ids }, }, }) //highlight-end }, }) }, }) ``` ## 5. Cleaning up ### 5.1. Clean up npm dependencies If you haven't already, you can now uninstall dependencies that were related to the Prisma 1 setup: ``` npm uninstall prisma1 prisma-client-lib ``` ### 5.2. Delete unused files Next, delete the files of your Prisma 1 setup: ``` rm -rf src/generated rm -rf prisma1 ``` ### 5.3. Stop the Prisma ORM server Finally, you can stop running your Prisma ORM server. --- # prisma-binding to Nexus URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-prisma-binding-to-nexus ## Overview :::info This guide is not fully up-to-date as it currently uses the [deprecated](https://github.com/graphql-nexus/nexus-plugin-prisma/issues/1039) version of the [`nexus-plugin-prisma`](https://github.com/graphql-nexus/nexus-plugin-prisma). While this is still functional, it is recommended to use the new [`nexus-prisma`](https://github.com/graphql-nexus/nexus-prisma) library or an alternative code-first GraphQL library like [Pothos](https://pothos-graphql.dev/) going forward. If you have any questions, join us on our [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=intro_text). ::: This upgrade guide describes how to migrate a Node.js project that's based on [Prisma 1](https://github.com/prisma/prisma1) and uses `prisma-binding` to implement a GraphQL server. The code will be migrated to [`@nexus/schema`](https://github.com/graphql-nexus/nexus) and the [`nexus-plugin-prisma`](https://github.com/graphql-nexus/nexus-plugin-prisma). As opposed to the _SDL-first_ approach that's used with `prisma-binding`, Nexus follows a code-first approach to construct GraphQL schemas. You can learn about the main differences of these two approaches in this [article](https://www.prisma.io/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3). If you want to continue using the SDL-first approach, you can follow the [guide](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-prisma-binding-to-sdl-first) to upgrade from `prisma-binding` to an SDL-first setup. This guide also explains how to migrate from JavaScript to TypeScript, it therefore basically assumes a **full rewrite** of your existing app. If you want to keep running your application in JavaScript, you can ignore the instructions that relate to the TypeScript setup keep using JavaScript as before. The guide assumes that you already went through the [guide for upgrading the Prisma ORM layer](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-the-prisma-layer-postgresql). This means you already: - installed the Prisma ORM 2.0 CLI - created your Prisma ORM 2.0 schema - introspected your database and resolved potential [schema incompatibilities](/orm/more/upgrade-guides/upgrade-from-prisma-1/schema-incompatibilities-postgresql) - installed and generated Prisma Client The guide further assumes that you have a file setup that looks similar to this: ``` . ├── README.md ├── package.json ├── prisma │ └── schema.prisma ├── prisma1 │ ├── datamodel.prisma │ └── prisma.yml └── src ├── generated │ └── prisma.graphql ├── index.js └── schema.graphql ``` The important parts are: - A folder called with `prisma` with your Prisma ORM 2.0 schema - A folder called `src` with your application code and a schema called `schema.graphql` If this is not what your project structure looks like, you'll need to adjust the instructions in the guide to match your own setup. ## 1. Installing and configuring Nexus ### 1.1. Install Nexus dependencies The first step is to install the Nexus dependency in your project: ```terminal copy npm install @nexus/schema ``` Next, install the the Prisma ORM plugin for Nexus which will allow you to expose Prisma models in your GraphQL API: ```terminal copy npm install nexus-plugin-prisma ``` The `nexus-plugin-prisma` dependency bundles all required Prisma ORM dependencies. You should therefore remove the dependencies that you installed when you upgraded the Prisma ORM layer of your app: ```terminal copy npm uninstall @prisma/cli @prisma/client ``` Note however that you can still invoke the Prisma ORM 2.0 CLI with the familiar command: ```terminal npx prisma ``` ### 1.2. Configure TypeScript Since you'll be using TypeScript in this guide, you need to add the required dependencies: ```terminal copy npm install typescript ts-node-dev --save-dev ``` Create a new file named `tsconfig.json` in the root directory of your project: ```terminal copy touch tsconfig.json ``` Now add the following contents to the new file: ```json copy file=tsconfig.json showLineNumbers { "compilerOptions": { "skipLibCheck": true, "strict": true, "rootDir": "src", "noEmit": true }, "include": ["src/**/*"] } ``` ### 1.3. Create your basic Nexus setup Create the root source file of your API called `index.ts` inside the `src` directory: ```terminal copy touch src/index.ts ``` Note that for this guide, you'll write the entire application inside of `index.ts`. In practice, you probably want to split your GraphQL types across different files as shown in this [example](https://pris.ly/e/ts/graphql-auth). For some basic setup, add this code to `index.ts`: ```ts file=index.ts showLineNumbers import { queryType, makeSchema } from '@nexus/schema' import { nexusSchemaPrisma } from 'nexus-plugin-prisma/schema' import { GraphQLServer } from 'graphql-yoga' import { createContext } from './context' const Query = queryType({ definition(t) { t.string('hello', () => { return 'Hello Nexus!' }) }, }) export const schema = makeSchema({ types: [Query], plugins: [nexusSchemaPrisma({ experimentalCRUD: true })], outputs: { schema: __dirname + '/../schema.graphql', typegen: __dirname + '/generated/nexus.ts', }, typegenAutoConfig: { contextType: 'Context.Context', sources: [ { source: '@prisma/client', alias: 'prisma', }, { source: require.resolve('./context'), alias: 'Context', }, ], }, }) new GraphQLServer({ schema, context: createContext() }).start(() => console.log(`Server ready at: http://localhost:4000`) ) ``` Note that this setup already contains the configuration of the Prisma ORM plugin for Nexus. This will enable the `t.model` and `t.crud` functionality that you'll get to know later in this guide. In the `typegenAutoConfig` setting, you're providing additional types that help your editor to provide your autocompletion as you develop your app. Right now it references a file named `context.ts` that you don't have in your project yet. This file will contain the type of your `context` object that's passed through your GraphQL resolver chain. Create the new `context.ts` file inside the `src` directory: ```terminal copy touch src/context.ts ``` Now add the following code to it: ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() export interface Context { prisma: PrismaClient } export function createContext(): Context { return { prisma } } ``` Next, adjust the `scripts` section inside your `package.json` to include the following commands: ```json { "scripts": { "start": "node dist/server", "clean": "rm -rf dist", "build": "npm -s run clean && npm -s run generate && tsc", "generate": "npm -s run generate:prisma && npm -s run generate:nexus", "generate:prisma": "prisma generate", "generate:nexus": "ts-node --transpile-only src/schema", "dev": "ts-node-dev --no-notify --respawn --transpile-only src" } } ``` The `dev` script starts a development server that you **always** should have running in the background when developing your app. This is important because of the code generation Nexus performs in the background. You can start the development server using the following command: ```copy npm run dev ``` You should see the following CLI output: ```terminal Server ready at: http://localhost:4000 ``` Your GraphQL server is now running at [http://localhost:4000](http://localhost:4000). So far it implements a single GraphQL query that you can send as follows: ```graphql { hello } ``` In the following steps, we'll explain how you can migrate your existing SDL-first GraphQL schema that's implemented with `prisma-binding` to an equivalent setup using Nexus. ## 2. Create your GraphQL types The next step of the upgrade process is to create your _GraphQL types_. In this case, your GraphQL types will mirror the Prisma models (as it likely was the case in your `prisma-binding` setup as well). If a GraphQL type deviates from a Prisma model, you'll be able to easily adjust the exposed GraphQL type accordingly using the Nexus API. For the purpose of this guide, you'll keep all the code in a single file. However, you can structure the files to your personal preference and `import` accordingly. In Nexus, GraphQL types are defined via the `objectType` function. Import `objectType` and then start with the skeleton for your first GraphQL type. In this case, we're starting by mapping Prisma schema's `User` model to GraphQL: ```ts copy import { objectType } from 'nexus' const User = objectType({ name: 'User', definition(t) { // the fields of the type will be defined here }, }) ``` With this code in place, you can start exposing the _fields_ of the `User` model one by one. You can use your editor's autocompletion to save some typing. Inside the body of the `definition` function, type `t.model.` and then hit CTRL+SPACE. This will bring up the autocompletion and suggest all fields that are defined on the `User` model: ![Exposing Prisma model fields with t.model](./images/expose-prisma-model-fields-with-t-model.png) Note that the `model` property on `t` is provided by the `nexus-plugin-prisma`. It leverages the type information from your Prisma schema and lets you expose your Prisma models via GraphQL. In that manner, you can start completing your object type definition until you exposed all the fields of the model: ```ts const User = objectType({ name: 'User', definition(t) { t.model.id() t.model.email() t.model.name() t.model.jsonData() t.model.role() t.model.profile() t.model.posts() }, }) ``` At this point, any _relation fields_ might give you TypeScript errors (in this case, that would be `profile` and `posts` which both point to other object types). That's expected, these errors will resolve automatically after you've added the remaining types. > **Note**: Be sure to have your Nexus development server that you started with `npm run dev` running all the time. It constantly updates the generated Nexus types that enable the autocompletion in the background as you save a file. Note that the `t.model.posts` relation exposes a _list_ of `Post` objects. By default, Nexus exposes only _pagination_ properties for that list – if you want to add _ordering_ and _filtering_ for that relation as well, you'll need to explicitly enable those: ```ts line-number highlight=10-13;add const User = objectType({ name: 'User', definition(t) { t.model.id() t.model.email() t.model.name() t.model.jsonData() t.model.role() t.model.profile() //add-start t.model.posts({ filtering: true, ordering: true, }) //add-end }, }) ``` After defining a type using the `objectType` function, you also need to manually add it to your GraphQL schema that you're building with Nexus. You can do it by adding it to the `types` which are provided as an option to the `makeSchema` function: ```ts line-number export const schema = makeSchema({ types: [Query, User], plugins: [nexusSchemaPrisma()], outputs: { schema: __dirname + '/../schema.graphql', typegen: __dirname + '/generated/nexus.ts', }, typegenAutoConfig: { sources: [ { source: '@prisma/client', alias: 'prisma', }, ], }, }) ``` Once you're done with the first type, you can start defining the remaining ones.
Expand to view the full version of the sample data model To expose all sample Prisma models with Nexus, the following code is needed: ```ts const User = objectType({ name: 'User', definition(t) { t.model.id() t.model.email() t.model.name() t.model.jsonData() t.model.role() t.model.profile() t.model.posts({ filtering: true, ordering: true, }) }, }) const Post = objectType({ name: 'Post', definition(t) { t.model.id() t.model.createdAt() t.model.updatedAt() t.model.title() t.model.content() t.model.published() t.model.author() t.model.authorId() t.model.categories({ filtering: true, ordering: true, }) }, }) const Profile = objectType({ name: 'Profile', definition(t) { t.model.id() t.model.bio() t.model.userId() t.model.user() }, }) const Category = objectType({ name: 'Category', definition(t) { t.model.id() t.model.name() t.model.posts({ filtering: true, ordering: true, }) }, }) ```
Be sure to include all newly defined types in the `types` option that's provided to `makeSchema`: ```ts line-number highlight=2;normal export const schema = makeSchema({ //highlight-next-line types: [Query, User, Post, Profile, Category], plugins: [nexusSchemaPrisma()], outputs: { schema: __dirname + '/../schema.graphql', typegen: __dirname + '/generated/nexus.ts', }, typegenAutoConfig: { sources: [ { source: '@prisma/client', alias: 'prisma', }, ], }, }) ``` You can view the current version of your GraphQL schema in SDL in the generated GraphQL schema file in `./schema.graphql`. ## 3. Migrate GraphQL operations As a next step, you can start migrating all the GraphQL _queries_ and _mutations_ from the "previous" GraphQL API to the new one that's built with Nexus. For this guide, the following sample GraphQL schema will be used: ```graphql # import Post from './generated/prisma.graphql' # import User from './generated/prisma.graphql' # import Category from './generated/prisma.graphql' input UserUniqueInput { id: String email: String } type Query { posts(searchString: String): [Post!]! user(userUniqueInput: UserUniqueInput!): User users(where: UserWhereInput, orderBy: Enumerable, skip: Int, after: String, before: String, first: Int, last: Int): [User]! } type Mutation { createUser(data: UserCreateInput!): User! createDraft(title: String!, content: String, authorId: ID!): Post updateBio(userUniqueInput: UserUniqueInput!, bio: String!): User addPostToCategories(postId: String!, categoryIds: [String!]!): Post } ``` ### 3.1. Migrate GraphQL queries In this section, you'll migrate all GraphQL _queries_ from `prisma-binding` to Nexus. #### 3.1.1. Migrate the `users` query (which uses `forwardTo`) In our sample API, the `users` query from the sample GraphQL schema is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Query { users(where: UserWhereInput, orderBy: Enumerable, skip: Int, after: String, before: String, first: Int, last: Int): [User]! # ... other queries } ``` ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Query: { users: forwardTo('prisma'), // ... other resolvers }, } ``` To mirror the same behaviour with Nexus, you can use the `crud` property on the `t` variable inside the `definition` function. Similar to `model`, this property is available because you're using the `nexus-prisma-plugin` which leverages type information from your Prisma models and auto-generates resolvers under the hood. The `crud` property also supports autocompletion, so you can explore all available queries in your editor again: ![Using t.crud to generate resolvers](./images/use-t-crud-to-generate-resolvers.png) ##### Forwarding the query with the `nexus-prisma-plugin` To add the `users` query to your GraphQL API, add the following lines to the query type definition: ```ts line-number highlight=3-6;add const Query = queryType({ definition(t) { //add-start t.crud.users({ filtering: true, ordering: true, }) //add-end }, }) ``` If you have the Nexus development server running, you can save the file and your GraphQL API will be updated to expose the new `users` query. You can also observe this by looking at the `Query` type inside the generated `schema.graphql` file: ```graphql type Query { users(after: UserWhereUniqueInput, before: UserWhereUniqueInput, first: Int, last: Int, orderBy: Enumerable, skip: Int, where: UserWhereInput): [User!]! } ``` You can now write your first query against the new API, e.g.: ```graphql { users { id name profile { id bio } posts { id title categories { id name } } } } ``` If your application exposes all CRUD operations from Prisma ORM using `forwardTo`, you can now continue adding all remaining ones using the same approach via `t.crud`. To learn how "custom" queries can be defined and resolved using Nexus, move on to the next sections. #### 3.1.2. Migrate the `posts(searchString: String): [Post!]!` query The `posts` query is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Query { posts(searchString: String): [Post!]! # ... other queries } ``` ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Query: { posts: (_, args, context, info) => { return context.prisma.query.posts( { where: { OR: [ { title_contains: args.searchString }, { content_contains: args.searchString }, ], }, }, info ) }, // ... other resolvers }, } ``` ##### Code-first schema definition with `nexus` To get the same behavior with Nexus, you'll need to add a `t.field` definition to the `queryType`: ```ts line-number highlight=5-9;add const Query = queryType({ definition(t) { // ... previous queries //add-start t.list.field('posts', { type: 'Post', nullable: false, args: { searchString: stringArg() }, }) //add-end }, }) ``` Although this code gives probably gives you a type error in your editor, you can already look at the generated SDL version of your GraphQL schema inside `schema.graphql`. You'll notice that this has added the correct _definition_ to your GraphQL schema already: ```graphql line-number type Query { //highlight-next-line posts(searchString: String): [Post!]! users(after: UserWhereUniqueInput, before: UserWhereUniqueInput, first: Int, last: Int, orderBy: Enumerable, skip: Int, where: UserWhereInput): [User!]! } ``` However, the code is missing the actual resolver logic. This is what you're going to add next. ##### Resolver implementation with `nexus` You can add the resolver with Nexus as follows: ```ts line-number highlight=9-21;add const Query = queryType({ definition(t) { // ... previous queries t.list.field('posts', { type: 'Post', nullable: false, args: { searchString: stringArg() }, //add-start resolve: (_, args, context) => { return context.prisma.post.findMany({ where: { OR: [ { title: { contains: args.searchString }, }, { content: { contains: args.searchString }, }, ], }, }) //add-end }, }) }, }) ``` To validate the implementation, you can now e.g. send the following example query to your GraphQL server: ```graphql { posts { id title author { id name } } } ``` #### 3.1.2. Migrate the `user(uniqueInput: UserUniqueInput): User` query In our sample app, the `user` query is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Query { user(userUniqueInput: UserUniqueInput): User # ... other queries } input UserUniqueInput { id: String email: String } ``` Note that this is a bit of a contrived example to demonstrate the usage of `input` types with Nexus. ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Query: { user: (_, args, context, info) => { return context.prisma.query.user( { where: args.userUniqueInput, }, info ) }, // ... other resolvers }, } ``` ##### Code-first schema definition with `nexus` To get the same behavior with Nexus, you'll need to add a `t.field` definition to the `queryType` and define an `inputObjectType` that includes the two `@unique` fields of your `User` model: ```ts line-number highlight=1,3-9,15-23;add //add-next-line import { inputObjectType, arg } from '@nexus/schema' //add-start const UserUniqueInput = inputObjectType({ name: 'UserUniqueInput', definition(t) { t.string('id') t.string('email') }, }) //add-end const Query = queryType({ definition(t) { // ... previous queries //add-start t.field('user', { type: 'User', args: { userUniqueInput: arg({ type: 'UserUniqueInput', nullable: false, }), }, }) //add-end }, }) ``` Since `UserUniqueInput` is a new type in your GraphQL schema, you again need to add it to the `types` option that's passed to `makeSchema`: ```ts line-number highlight=2;normal export const schema = makeSchema({ //highlight-next-line types: [Query, User, Post, Profile, Category, UserUniqueInput], plugins: [nexusSchemaPrisma()], outputs: { schema: __dirname + '/../schema.graphql', typegen: __dirname + '/generated/nexus.ts', }, typegenAutoConfig: { sources: [ { source: '@prisma/client', alias: 'prisma', }, ], }, }) ``` If you look at the generated SDL version of your GraphQL schema inside `schema.graphql`, you'll notice that this change already added the correct _definition_ to your GraphQL schema: ```graphql line-number highlight=3,7-10;normal type Query { posts(searchString: String): [Post!] //highlight-next-line user(userUniqueInput: UserUniqueInput!): User users(after: UserWhereUniqueInput, before: UserWhereUniqueInput, first: Int, last: Int, orderBy: Enumerable, skip: Int, where: UserWhereInput): [User!]! } //highlight-start input UserUniqueInput { email: String id: String } //highlight-end ``` You can even send the respective query via the GraphQL Playground already: ```graphql { user(userUniqueInput: { email: "alice@prisma.io" }) { id name } } ``` However, because the resolver is not yet implemented you will not get any data back yet. ##### Code-first resolver implementation with `nexus` That's because you're still missing the _resolver_ implementation for that query. You can add the resolver with Nexus as follows: ```ts line-number highlight=22-29;add const UserUniqueInput = inputObjectType({ name: 'UserUniqueInput', definition(t) { t.string('id') t.string('email') }, }) const Query = queryType({ definition(t) { // ... previous queries t.field('user', { type: 'User', nullable: true, args: { userUniqueInput: arg({ type: 'UserUniqueInput', nullable: false, }), }, //add-start resolve: (_, args, context) => { return context.prisma.user.findUnique({ where: { id: args.userUniqueInput?.id, email: args.userUniqueInput?.email, }, }) }, //add-end }) }, }) ``` If you're re-sending the same query from before, you'll find that it now returns actual data. ### 3.2. Migrate GraphQL mutations In this section, you'll migrate the GraphQL mutations from the sample schema to the Nexus. #### 3.2.1. Define the `Mutation` type The first step to migrate any mutations is to define the `Mutation` type of your GraphQL API. Once that's done, you can gradually add operations to it. Add the following definition to `index.ts`: ```ts import { mutationType } from '@nexus/schema' const Mutation = mutationType({ definition(t) { // your GraphQL mutations + resolvers will be defined here }, }) ``` In order to make sure that the new `Mutation` type is picked by up Nexus, you need to add it to the `types` that are provided to `makeSchema`: ```ts line-number highlight=2;normal export const schema = makeSchema({ //highlight-next-line types: [Query, User, Post, Profile, Category, UserUniqueInput, Mutation], plugins: [nexusSchemaPrisma()], outputs: { schema: __dirname + '/../schema.graphql', typegen: __dirname + '/generated/nexus.ts', }, typegenAutoConfig: { sources: [ { source: '@prisma/client', alias: 'prisma', }, ], }, }) ``` #### 3.2.2. Migrate the `createUser` mutation (which uses `forwardTo`) In the sample app, the `createUser` mutation from the sample GraphQL schema is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Mutation { createUser(data: UserCreateInput!): User! # ... other mutations } ``` ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Mutation: { createUser: forwardTo('prisma'), // ... other resolvers }, } ``` Similar to forwarding GraphQL queries, you can use the `crud` property on the `t` variable inside the `definition` function in order to expose full CRUD capabilities for Prisma models. Similar to `model`, this property is available because you're using the `nexus-prisma-plugin` which leverages type information from your Prisma models and auto-generates resolvers under the hood. The `crud` property supports autocompletion when defining mutations as well, so you can explore all available operations in your editor again: ![Generating resolvers with t.crud](./images/regenerate-resolvers-with-t-crud.png) ##### Forwarding the mutation with the `nexus-prisma-plugin` To add the `createUser` mutation to your GraphQL API, add the following lines to the query type definition: ```ts line-number highlight=3-5;add const Mutation = mutationType({ definition(t) { //add-start t.crud.createOneUser({ alias: 'createUser', }) //add-end }, }) ``` Note that the default name for the mutation in your GraphQL schema is `createOneUser` (named after the function which is exposed by `t.crud`). In order to rename it to `createUser`, you need to provide the `alias` property. If you have the Nexus development server running, you can save the file and your GraphQL API will be updated to expose the new `createUser` mutation. You can also observe this by looking at the `Mutation` type inside the generated `schema.graphql` file: ```graphql type Mutation { createUser(data: UserCreateInput!): User! } ``` You can now write your first mutation against the new API, e.g.: ```graphql mutation { createUser(data: { name: "Alice", email: "alice@prisma.io" }) { id } } ``` If your application exposes all CRUD operations from Prisma Client using `forwardTo`, you can now continue adding all remaining ones using the same approach via `t.crud`. To learn how "custom" mutations can be defined and resolved using Nexus, move on to the next sections. #### 3.2.3. Migrate the `createDraft(title: String!, content: String, authorId: String!): Post!` query In the sample app, the `createDraft` mutation is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Mutation { createDraft(title: String!, content: String, authorId: String!): Post! # ... other mutations } ``` ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Mutation: { createDraft: (_, args, context, info) => { return context.prisma.mutation.createPost( { data: { title: args.title, content: args.content, author: { connect: { id: args.authorId, }, }, }, }, info ) }, // ... other resolvers }, } ``` ##### Code-first schema definition with `nexus` To get the same behavior with Nexus, you'll need to add a `t.field` definition to the `mutationType`: ```ts line-number highlight=5-12;add const Mutation = mutationType({ definition(t) { // ... previous mutations //add-start t.field('createDraft', { type: 'Post', args: { title: stringArg({ nullable: false }), content: stringArg(), authorId: stringArg({ nullable: false }), }, }) //add-end }, }) ``` If you look at the generated SDL version of your GraphQL schema inside `schema.graphql`, you'll notice that this has added the correct _definition_ to your GraphQL schema already: ```graphql line-number highlight=3;normal type Mutation { createUser(data: UserCreateInput!): User! //highlight-next-line createDraft(title: String!, content: String, authorId: String!): Post! } ``` You can even send the respective mutation via the GraphQL Playground already: ```graphql mutation { createDraft(title: "Hello World", authorId: "__AUTHOR_ID__") { id published author { id name } } } ``` However, because the resolver is not yet implemented, no new `Post` record will be created and you will not get any data back in the response. ##### Resolver implementation with `nexus` That's because you're still missing the _resolver_ implementation for that mutation. You can add the resolver with Nexus as follows: ```ts line-number highlight=12-22;add const Mutation = mutationType({ definition(t) { // ... previous mutations t.field('createDraft', { type: 'Post', args: { title: stringArg({ nullable: false }), content: stringArg(), authorId: stringArg({ nullable: false }), }, //add-start resolve: (_, args, context) => { return context.prisma.post.create({ data: { title: args.title, content: args.content, author: { connect: { id: args.authorId }, }, }, }) }, //add-end }) }, }) ``` If you're re-sending the same query from before, you'll find that it now create a new `Post` record and return valid data. #### 3.2.4. Migrate the `updateBio(bio: String, userUniqueInput: UserUniqueInput!): User` mutation In the sample app, the `updateBio` mutation is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Mutation { updateBio(bio: String!, userUniqueInput: UserUniqueInput!): User # ... other mutations } ``` ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Mutation: { updateBio: (_, args, context, info) => { return context.prisma.mutation.updateUser( { data: { profile: { update: { bio: args.bio }, }, }, where: { id: args.userId }, }, info ) }, // ... other resolvers }, } ``` ##### Code-first schema definition with `nexus` To get the same behavior with Nexus, you'll need to add a `t.field` definition to the `mutationType`: ```ts line-number highlight=5-14;add const Mutation = mutationType({ definition(t) { // ... previous mutations //add-start t.field('updateBio', { type: 'User', args: { userUniqueInput: arg({ type: 'UserUniqueInput', nullable: false, }), bio: stringArg({ nullable: false }), }, }) //add-end }, }) ``` If you look at the generated SDL version of your GraphQL schema inside `schema.graphql`, you'll notice that this has added the correct _definition_ to your GraphQL schema already: ```graphql line-number highlight=4;normal type Mutation { createUser(data: UserCreateInput!): User! createDraft(title: String!, content: String, authorId: String!): Post! //highlight-next-line updateBio(bio: String!, userUniqueInput: UserUniqueInput!): User } ``` You can even send the respective mutation via the GraphQL Playground already: ```graphql mutation { updateBio( userUniqueInput: { email: "alice@prisma.io" } bio: "I like turtles" ) { id name profile { id bio } } } ``` However, because the resolver is not yet implemented, nothing will be updated in the database and you will not get any data back in the response. ##### Resolver implementation with `nexus` That's because you're still missing the _resolver_ implementation for that query. You can add the resolver with Nexus as follows: ```ts line-number highlight=14-26;add const Mutation = mutationType({ definition(t) { // ... previous mutations t.field('updateBio', { type: 'User', args: { userUniqueInput: arg({ type: 'UserUniqueInput', nullable: false }), bio: stringArg() }, //add-start resolve: (_, args, context) => { return context.prisma.user.update({ where: { id: args.userUniqueInput?.id, email: args.userUniqueInput?.email }, data: { profile: { create: { bio: args.bio } } } }) } //add-end } } }) ``` If you're re-sending the same query from before, you'll find that it now returns actual data instead of `null`. #### 3.2.5. Migrate the `addPostToCategories(postId: String!, categoryIds: [String!]!): Post` mutation In our sample app, the `addPostToCategories` mutation is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Mutation { addPostToCategories(postId: String!, categoryIds: [String!]!): Post # ... other mutations } ``` ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Mutation: { addPostToCategories: (_, args, context, info) => { const ids = args.categoryIds.map((id) => ({ id })) return context.prisma.mutation.updatePost( { data: { categories: { connect: ids, }, }, where: { id: args.postId, }, }, info ) }, // ... other resolvers }, } ``` ##### Code-first schema definition with `nexus` To get the same behavior with Nexus, you'll need to add a `t.field` definition to the `mutationType`: ```ts line-number highlight=5-14;add const Mutation = mutationType({ definition(t) { // ... mutations from before //add-start t.field('addPostToCategories', { type: 'Post', args: { postId: stringArg({ nullable: false }), categoryIds: stringArg({ list: true, nullable: false, }), }, }) //add-end }, }) ``` If you look at the generated SDL version of your GraphQL schema inside `schema.graphql`, you'll notice that this has added the correct _definition_ to your GraphQL schema already: ```graphql line-number highlight=5;normal type Mutation { createUser(data: UserCreateInput!): User! createDraft(title: String!, content: String, authorId: String!): Post! updateBio(bio: String, userUniqueInput: UserUniqueInput!): User //highlight-next-line addPostToCategories(postId: String!, categoryIds: [String!]!): Post } ``` You can even send the respective query via the GraphQL Playground already: ```graphql mutation { addPostToCategories( postId: "__AUTHOR_ID__" categoryIds: ["__CATEGORY_ID_1__", "__CATEGORY_ID_2__"] ) { id title categories { id name } } } ``` However, because the resolver is not yet implemented, nothing will be updated in the database and you will not get any data back in the response. ##### Resolver implementation with `nexus` That's because you're still missing the _resolver_ implementation for that query. You can add the resolver with Nexus as follows: ```ts line-number highlight=13-23;add const Mutation = mutationType({ definition(t) { // ... mutations from before t.field('addPostToCategories', { type: 'Post', args: { postId: stringArg({ nullable: false }), categoryIds: stringArg({ list: true, nullable: false, }), }, //add-start resolve: (_, args, context) => { const ids = args.categoryIds.map((id) => ({ id })) return context.prisma.post.update({ where: { id: args.postId, }, data: { categories: { connect: ids }, }, }) }, //add-end }) }, }) ``` If you're re-sending the same query from before, you'll find that it now returns actual data instead of `null`. ## 4. Cleaning up Since the entire app has now been upgrade to Prisma ORM 2.0 and Nexus, you can delete all unnecessary files and remove the no longer needed dependencies. ### 4.1. Clean up npm dependencies You can start by removing npm dependencies that were related to the Prisma 1 setup: ```copy npm uninstall graphql-cli prisma-binding prisma1 ``` ### 4.2. Delete unused files Next, delete the files of your Prisma 1 setup: ```copy rm prisma1/datamodel.prisma prisma1/prisma.yml ``` You can also delete any remaining `.js` files, the old `schema.graphql` and `prisma.graphql` files. ### 4.3. Stop the Prisma ORM server Finally, you can stop running your Prisma ORM server. --- # prisma-binding to SDL-first URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-prisma-binding-to-sdl-first ## Overview This upgrade guide describes how to migrate a Node.js project that's based on [Prisma 1](https://github.com/prisma/prisma1) and uses `prisma-binding` to implement a GraphQL server. The code will keep the [SDL-first approach](https://www.prisma.io/blog/the-problems-of-schema-first-graphql-development-x1mn4cb0tyl3) for constructing the GraphQL schema. When migrating from `prisma-binding` to Prisma Client, the main difference is that the `info` object can't be used to resolve relations automatically any more, instead you'll need to implement your _type resolvers_ to ensure that relations get resolved properly. The guide assumes that you already went through the [guide for upgrading the Prisma ORM layer](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-the-prisma-layer-postgresql). This means you already: - installed the Prisma ORM 2 CLI - created your Prisma ORM 2 schema - introspected your database and resolved potential schema incompatibilities - installed and generated Prisma Client The guide further assumes that you have a file setup that looks similar to this: ``` . ├── README.md ├── package.json ├── prisma │ └── schema.prisma ├── prisma1 │ ├── datamodel.prisma │ └── prisma.yml └── src ├── generated │ └── prisma.graphql ├── index.js └── schema.graphql ``` The important parts are: - A folder called with `prisma` with your Prisma ORM 2 schema - A folder called `src` with your application code and a schema called `schema.graphql` If this is not what your project structure looks like, you'll need to adjust the instructions in the guide to match your own setup. ## 1. Adjusting your GraphQL schema With `prisma-binding`, your approach for defining your GraphQL schema (sometimes called [application schema](https://v1.prisma.io/docs/1.20/data-model-and-migrations/data-model-knul/#a-note-on-the-application-schema)) is based on _importing_ GraphQL types from the generated `prisma.graphql` file (in Prisma 1, this is typically called [Prisma GraphQL schema](https://v1.prisma.io/docs/1.20/data-model-and-migrations/data-model-knul/#the-prisma-graphql-schema)). These types mirror the types from your Prisma 1 datamodel and serve as foundation for your GraphQL API. With Prisma ORM 2, there's no `prisma.graphql` file any more that you could import from. Therefore, you have to spell out all the types of your GraphQL schema directly inside your `schema.graphql` file. The easiest way to do so is by downloading the full GraphQL schema from the GraphQL Playground. To do so, open the **SCHEMA** tab and click the **DOWNLOAD** button in the top-right corner, then select **SDL**: ![Downloading the GraphQL schema with GraphQL Playground](./images/download-graphql-schema.png) Alternatively, you can use the `get-schema` command of the [GraphQL CLI](https://github.com/Urigo/graphql-cli) to download your full schema: ``` npx graphql get-schema --endpoint __GRAPHQL_YOGA_ENDPOINT__ --output schema.graphql --no-all ``` > **Note**: With the above command, you need to replace the `__GRAPHQL_YOGA_ENDPOINT__` placeholder with the actual endpoint of your GraphQL Yoga server. Once you obtained the `schema.graphql` file, replace your current version in `src/schema.graphql` with the new contents. Note that the two schemas are 100% equivalent, except that the new one doesn't use [`graphql-import`](https://github.com/ardatan/graphql-import) for importing types from a different file. Instead, it spells out all types in a single file. Here's a comparison of these two versions of the sample GraphQL schema that we'll migrate in this guide (you can use the tabs to switch between the two versions): ```graphql # import Post from './generated/prisma.graphql' # import User from './generated/prisma.graphql' # import Category from './generated/prisma.graphql' type Query { posts(searchString: String): [Post!]! user(userUniqueInput: UserUniqueInput!): User users(where: UserWhereInput, orderBy: Enumerable, skip: Int, after: String, before: String, first: Int, last: Int): [User]! allCategories: [Category!]! } input UserUniqueInput { id: String email: String } type Mutation { createDraft(authorId: ID!, title: String!, content: String!): Post publish(id: ID!): Post deletePost(id: ID!): Post signup(name: String!, email: String!): User! updateBio(userId: String!, bio: String!): User addPostToCategories(postId: String!, categoryIds: [String!]!): Post } ``` ```graphql type Query { posts(searchString: String): [Post!]! user(id: ID!): User users(where: UserWhereInput, orderBy: Enumerable, skip: Int, after: String, before: String, first: Int, last: Int): [User]! allCategories: [Category!]! } type Category implements Node { id: ID! name: String! posts(where: PostWhereInput, orderBy: Enumerable, skip: Int, after: String, before: String, first: Int, last: Int): [Post!] } input CategoryCreateManyWithoutPostsInput { create: [CategoryCreateWithoutPostsInput!] connect: [CategoryWhereUniqueInput!] } input CategoryCreateWithoutPostsInput { id: ID name: String! } enum CategoryOrderByInput { id_ASC id_DESC name_ASC name_DESC } input CategoryWhereInput { """Logical AND on all given filters.""" AND: [CategoryWhereInput!] """Logical OR on all given filters.""" OR: [CategoryWhereInput!] """Logical NOT on all given filters combined by AND.""" NOT: [CategoryWhereInput!] id: ID """All values that are not equal to given value.""" id_not: ID """All values that are contained in given list.""" id_in: [ID!] """All values that are not contained in given list.""" id_not_in: [ID!] """All values less than the given value.""" id_lt: ID """All values less than or equal the given value.""" id_lte: ID """All values greater than the given value.""" id_gt: ID """All values greater than or equal the given value.""" id_gte: ID """All values containing the given string.""" id_contains: ID """All values not containing the given string.""" id_not_contains: ID """All values starting with the given string.""" id_starts_with: ID """All values not starting with the given string.""" id_not_starts_with: ID """All values ending with the given string.""" id_ends_with: ID """All values not ending with the given string.""" id_not_ends_with: ID name: String """All values that are not equal to given value.""" name_not: String """All values that are contained in given list.""" name_in: [String!] """All values that are not contained in given list.""" name_not_in: [String!] """All values less than the given value.""" name_lt: String """All values less than or equal the given value.""" name_lte: String """All values greater than the given value.""" name_gt: String """All values greater than or equal the given value.""" name_gte: String """All values containing the given string.""" name_contains: String """All values not containing the given string.""" name_not_contains: String """All values starting with the given string.""" name_starts_with: String """All values not starting with the given string.""" name_not_starts_with: String """All values ending with the given string.""" name_ends_with: String """All values not ending with the given string.""" name_not_ends_with: String posts_every: PostWhereInput posts_some: PostWhereInput posts_none: PostWhereInput } input CategoryWhereUniqueInput { id: ID } scalar DateTime """Raw JSON value""" scalar Json """An object with an ID""" interface Node { """The id of the object.""" id: ID! } type Post implements Node { id: ID! createdAt: DateTime! updatedAt: DateTime! title: String! content: String published: Boolean! author: User categories(where: CategoryWhereInput, orderBy: Enumerable, skip: Int, after: String, before: String, first: Int, last: Int): [Category!] } input PostCreateManyWithoutAuthorInput { create: [PostCreateWithoutAuthorInput!] connect: [PostWhereUniqueInput!] } input PostCreateWithoutAuthorInput { id: ID title: String! content: String published: Boolean categories: CategoryCreateManyWithoutPostsInput } enum PostOrderByInput { id_ASC id_DESC createdAt_ASC createdAt_DESC updatedAt_ASC updatedAt_DESC title_ASC title_DESC content_ASC content_DESC published_ASC published_DESC } input PostWhereInput { """Logical AND on all given filters.""" AND: [PostWhereInput!] """Logical OR on all given filters.""" OR: [PostWhereInput!] """Logical NOT on all given filters combined by AND.""" NOT: [PostWhereInput!] id: ID """All values that are not equal to given value.""" id_not: ID """All values that are contained in given list.""" id_in: [ID!] """All values that are not contained in given list.""" id_not_in: [ID!] """All values less than the given value.""" id_lt: ID """All values less than or equal the given value.""" id_lte: ID """All values greater than the given value.""" id_gt: ID """All values greater than or equal the given value.""" id_gte: ID """All values containing the given string.""" id_contains: ID """All values not containing the given string.""" id_not_contains: ID """All values starting with the given string.""" id_starts_with: ID """All values not starting with the given string.""" id_not_starts_with: ID """All values ending with the given string.""" id_ends_with: ID """All values not ending with the given string.""" id_not_ends_with: ID createdAt: DateTime """All values that are not equal to given value.""" createdAt_not: DateTime """All values that are contained in given list.""" createdAt_in: [DateTime!] """All values that are not contained in given list.""" createdAt_not_in: [DateTime!] """All values less than the given value.""" createdAt_lt: DateTime """All values less than or equal the given value.""" createdAt_lte: DateTime """All values greater than the given value.""" createdAt_gt: DateTime """All values greater than or equal the given value.""" createdAt_gte: DateTime updatedAt: DateTime """All values that are not equal to given value.""" updatedAt_not: DateTime """All values that are contained in given list.""" updatedAt_in: [DateTime!] """All values that are not contained in given list.""" updatedAt_not_in: [DateTime!] """All values less than the given value.""" updatedAt_lt: DateTime """All values less than or equal the given value.""" updatedAt_lte: DateTime """All values greater than the given value.""" updatedAt_gt: DateTime """All values greater than or equal the given value.""" updatedAt_gte: DateTime title: String """All values that are not equal to given value.""" title_not: String """All values that are contained in given list.""" title_in: [String!] """All values that are not contained in given list.""" title_not_in: [String!] """All values less than the given value.""" title_lt: String """All values less than or equal the given value.""" title_lte: String """All values greater than the given value.""" title_gt: String """All values greater than or equal the given value.""" title_gte: String """All values containing the given string.""" title_contains: String """All values not containing the given string.""" title_not_contains: String """All values starting with the given string.""" title_starts_with: String """All values not starting with the given string.""" title_not_starts_with: String """All values ending with the given string.""" title_ends_with: String """All values not ending with the given string.""" title_not_ends_with: String content: String """All values that are not equal to given value.""" content_not: String """All values that are contained in given list.""" content_in: [String!] """All values that are not contained in given list.""" content_not_in: [String!] """All values less than the given value.""" content_lt: String """All values less than or equal the given value.""" content_lte: String """All values greater than the given value.""" content_gt: String """All values greater than or equal the given value.""" content_gte: String """All values containing the given string.""" content_contains: String """All values not containing the given string.""" content_not_contains: String """All values starting with the given string.""" content_starts_with: String """All values not starting with the given string.""" content_not_starts_with: String """All values ending with the given string.""" content_ends_with: String """All values not ending with the given string.""" content_not_ends_with: String published: Boolean """All values that are not equal to given value.""" published_not: Boolean author: UserWhereInput categories_every: CategoryWhereInput categories_some: CategoryWhereInput categories_none: CategoryWhereInput } input PostWhereUniqueInput { id: ID } type Profile implements Node { id: ID! bio: String user: User! } input ProfileCreateOneWithoutUserInput { create: ProfileCreateWithoutUserInput connect: ProfileWhereUniqueInput } input ProfileCreateWithoutUserInput { id: ID bio: String } input ProfileWhereInput { """Logical AND on all given filters.""" AND: [ProfileWhereInput!] """Logical OR on all given filters.""" OR: [ProfileWhereInput!] """Logical NOT on all given filters combined by AND.""" NOT: [ProfileWhereInput!] id: ID """All values that are not equal to given value.""" id_not: ID """All values that are contained in given list.""" id_in: [ID!] """All values that are not contained in given list.""" id_not_in: [ID!] """All values less than the given value.""" id_lt: ID """All values less than or equal the given value.""" id_lte: ID """All values greater than the given value.""" id_gt: ID """All values greater than or equal the given value.""" id_gte: ID """All values containing the given string.""" id_contains: ID """All values not containing the given string.""" id_not_contains: ID """All values starting with the given string.""" id_starts_with: ID """All values not starting with the given string.""" id_not_starts_with: ID """All values ending with the given string.""" id_ends_with: ID """All values not ending with the given string.""" id_not_ends_with: ID bio: String """All values that are not equal to given value.""" bio_not: String """All values that are contained in given list.""" bio_in: [String!] """All values that are not contained in given list.""" bio_not_in: [String!] """All values less than the given value.""" bio_lt: String """All values less than or equal the given value.""" bio_lte: String """All values greater than the given value.""" bio_gt: String """All values greater than or equal the given value.""" bio_gte: String """All values containing the given string.""" bio_contains: String """All values not containing the given string.""" bio_not_contains: String """All values starting with the given string.""" bio_starts_with: String """All values not starting with the given string.""" bio_not_starts_with: String """All values ending with the given string.""" bio_ends_with: String """All values not ending with the given string.""" bio_not_ends_with: String user: UserWhereInput } input ProfileWhereUniqueInput { id: ID } enum Role { ADMIN CUSTOMER } type User implements Node { id: ID! email: String name: String! posts(where: PostWhereInput, orderBy: Enumerable, skip: Int, after: String, before: String, first: Int, last: Int): [Post!] role: Role! profile: Profile jsonData: Json } input UserCreateInput { id: ID email: String name: String! role: Role jsonData: Json posts: PostCreateManyWithoutAuthorInput profile: ProfileCreateOneWithoutUserInput } enum UserOrderByInput { id_ASC id_DESC email_ASC email_DESC name_ASC name_DESC role_ASC role_DESC jsonData_ASC jsonData_DESC } input UserWhereInput { """Logical AND on all given filters.""" AND: [UserWhereInput!] """Logical OR on all given filters.""" OR: [UserWhereInput!] """Logical NOT on all given filters combined by AND.""" NOT: [UserWhereInput!] id: ID """All values that are not equal to given value.""" id_not: ID """All values that are contained in given list.""" id_in: [ID!] """All values that are not contained in given list.""" id_not_in: [ID!] """All values less than the given value.""" id_lt: ID """All values less than or equal the given value.""" id_lte: ID """All values greater than the given value.""" id_gt: ID """All values greater than or equal the given value.""" id_gte: ID """All values containing the given string.""" id_contains: ID """All values not containing the given string.""" id_not_contains: ID """All values starting with the given string.""" id_starts_with: ID """All values not starting with the given string.""" id_not_starts_with: ID """All values ending with the given string.""" id_ends_with: ID """All values not ending with the given string.""" id_not_ends_with: ID email: String """All values that are not equal to given value.""" email_not: String """All values that are contained in given list.""" email_in: [String!] """All values that are not contained in given list.""" email_not_in: [String!] """All values less than the given value.""" email_lt: String """All values less than or equal the given value.""" email_lte: String """All values greater than the given value.""" email_gt: String """All values greater than or equal the given value.""" email_gte: String """All values containing the given string.""" email_contains: String """All values not containing the given string.""" email_not_contains: String """All values starting with the given string.""" email_starts_with: String """All values not starting with the given string.""" email_not_starts_with: String """All values ending with the given string.""" email_ends_with: String """All values not ending with the given string.""" email_not_ends_with: String name: String """All values that are not equal to given value.""" name_not: String """All values that are contained in given list.""" name_in: [String!] """All values that are not contained in given list.""" name_not_in: [String!] """All values less than the given value.""" name_lt: String """All values less than or equal the given value.""" name_lte: String """All values greater than the given value.""" name_gt: String """All values greater than or equal the given value.""" name_gte: String """All values containing the given string.""" name_contains: String """All values not containing the given string.""" name_not_contains: String """All values starting with the given string.""" name_starts_with: String """All values not starting with the given string.""" name_not_starts_with: String """All values ending with the given string.""" name_ends_with: String """All values not ending with the given string.""" name_not_ends_with: String role: Role """All values that are not equal to given value.""" role_not: Role """All values that are contained in given list.""" role_in: [Role!] """All values that are not contained in given list.""" role_not_in: [Role!] posts_every: PostWhereInput posts_some: PostWhereInput posts_none: PostWhereInput profile: ProfileWhereInput } ``` You'll notice that the new version of your GraphQL schema not only defines the _models_ that were imported directly, but also additional types (e.g. `input` types) that were not present in the schema before. ## 2. Set up your `PrismaClient` instance `PrismaClient` is your new interface to the database in Prisma ORM 2. It lets you invoke various methods which build SQL queries and send them to the database, returning the results as plain JavaScript objects. The `PrismaClient` query API is inspired by the initial `prisma-binding` API, so a lot of the queries you send with Prisma Client will feel familiar. Similar to the `prisma-binding` instance from Prisma 1, you also want to attach your `PrismaClient` from Prisma ORM 2 to GraphQL's `context` so that in can be accessed inside your resolvers: ```js line-number highlight=10-13;delete|14;add const { PrismaClient } = require('@prisma/client') // ... const server = new GraphQLServer({ typeDefs: 'src/schema.graphql', resolvers, context: (req) => ({ ...req, //delete-start prisma: new Prisma({ typeDefs: 'src/generated/prisma.graphql', endpoint: 'http://localhost:4466', }), //delete-end //add-next-line prisma: new PrismaClient(), }), }) ``` In the code block above, the _red_ lines are the lines to be removed from your current setup, the _green_ lines are the ones that you should add. Of course, it's possible that your previous setup differed from this one (e.g. it's unlikely that your Prisma ORM `endpoint` was `http://localhost:4466` if you're running your API in production), this is just a sample to indicate what it _could_ look like. When you're now accessing `context.prisma` inside of a resolver, you now have access to Prisma Client queries. ## 2. Write your GraphQL type resolvers `prisma-binding` was able to _magically_ resolve relations in your GraphQL schema. When not using `prisma-binding` though, you need to explicitly resolve your relations using so-called _type resolvers_. > **Note** You can learn more about the concept of type resolvers and why they're necessary in this article: [GraphQL Server Basics: GraphQL Schemas, TypeDefs & Resolvers Explained](https://www.prisma.io/blog/graphql-server-basics-the-schema-ac5e2950214e) ### 2.1. Implementing the type resolver for the `User` type The `User` type in our sample GraphQL schema is defined as follows: ```graphql type User implements Node { id: ID! email: String name: String! posts( where: PostWhereInput orderBy: Enumerable skip: Int after: String before: String first: Int last: Int ): [Post!] role: Role! profile: Profile jsonData: Json } ``` This type has two relations: - The `posts` field denotes a 1-n relation to `Post` - The `profile` field denotes a 1-1 relation to `Profile` Since you're not using `prisma-binding` any more, you now need to resolve these relations "manually" in type resolvers. You can do so by adding a `User` field to your _resolver map_ and implement the resolvers for the `posts` and `profile` relations as follows: ```js line-number highlight=8-23;add const resolvers = { Query: { // ... your query resolvers }, Mutation: { // ... your mutation resolvers }, //add-start User: { posts: (parent, args, context) => { return context.prisma.user .findUnique({ where: { id: parent.id }, }) .posts() }, profile: (parent, args, context) => { return context.prisma.user .findUnique({ where: { id: parent.id }, }) .profile() }, }, //add-end } ``` Inside of these resolvers, you're using your new `PrismaClient` to perform a query against the database. Inside the `posts` resolver, the database query loads all `Post` records from the specified `author` (whose `id` is carried in the `parent` object). Inside the `profile` resolver, the database query loads the `Profile` record from the specified `user` (whose `id` is carried in the `parent` object). Thanks to these extra resolvers, you'll now be able to nest relations in your GraphQL queries/mutations whenever you're requesting information about the `User` type in a query, e.g.: ```graphql { users { id name posts { # fetching this relation is enabled by the new type resolver id title } profile { # fetching this relation is enabled by the new type resolver id bio } } } ``` ### 2.2. Implementing the type resolver for the `Post` type The `Post` type in our sample GraphQL schema is defined as follows: ```graphql type Post implements Node { id: ID! createdAt: DateTime! updatedAt: DateTime! title: String! content: String published: Boolean! author: User categories( where: CategoryWhereInput orderBy: Enumerable skip: Int after: String before: String first: Int last: Int ): [Category!] } ``` This type has two relations: - The `author` field denotes a 1-n relation to `User` - The `categories` field denotes a m-n relation to `Category` Since you're not using `prisma-binding` any more, you now need to resolve these relations "manually" in type resolvers. You can do so by adding a `Post` field to your _resolver map_ and implement the resolvers for the `author` and `categories` relations as follows: ```js line-number highlight=11-26;add const resolvers = { Query: { // ... your query resolvers }, Mutation: { // ... your mutation resolvers }, User: { // ... your type resolvers for `User` from before }, //add-start Post: { author: (parent, args, context) => { return context.prisma.post .findUnique({ where: { id: parent.id }, }) .author() }, categories: (parent, args, context) => { return context.prisma.post .findUnique({ where: { id: parent.id }, }) .categories() }, }, //add-end } ``` Inside of these resolvers, you're using your new `PrismaClient` to perform a query against the database. Inside the `author` resolver, the database query loads the `User` record that represents the `author` of the `Post`. Inside the `categories` resolver, the database query loads all `Category` records from the specified `post` (whose `id` is carried in the `parent` object). Thanks to these extra resolvers, you'll now be able to nest relations in your GraphQL queries/mutations whenever you're requesting information about the `User` type in a query, e.g.: ```graphql { posts { id title author { # fetching this relation is enabled by the new type resolver id name } categories { # fetching this relation is enabled by the new type resolver id name } } } ``` ### 2.3. Implementing the type resolver for the `Profile` type The `Profile` type in our sample GraphQL schema is defined as follows: ```graphql type Profile implements Node { id: ID! bio: String user: User! } ``` This type has one relation: The `user` field denotes a 1-n relation to `User`. Since you're not using `prisma-binding` any more, you now need to resolve this relation "manually" in type resolvers. You can do so by adding a `Profile` field to your _resolver map_ and implement the resolvers for the `owner` relation as follows: ```js line-number highlight=14-22;add const resolvers = { Query: { // ... your query resolvers }, Mutation: { // ... your mutation resolvers }, User: { // ... your type resolvers for `User` from before }, Post: { // ... your type resolvers for `Post` from before }, //add-start Profile: { user: (parent, args, context) => { return context.prisma.profile .findUnique({ where: { id: parent.id }, }) .owner() }, }, //add-end } ``` Inside of this resolver, you're using your new `PrismaClient` to perform a query against the database. Inside the `user` resolver, the database query loads the `User` records from the specified `profile` (whose `id` is carried in the `parent` object). Thanks to this extra resolver, you'll now be able to nest relations in your GraphQL queries/mutations whenever you're requesting information about the `Profile` type in a query. ### 2.4. Implementing the type resolver for the `Category` type The `Category` type in our sample GraphQL schema is defined as follows: ```graphql type Category implements Node { id: ID! name: String! posts( where: PostWhereInput orderBy: Enumerable skip: Int after: String before: String first: Int last: Int ): [Post!] } ``` This type has one relation: The `posts` field denotes a m-n relation to `Post`. Since you're not using `prisma-binding` any more, you now need to resolve this relation "manually" in type resolvers. You can do so by adding a `Category` field to your _resolver map_ and implement the resolvers for the `posts` and `profile` relations as follows: ```js line-number highlight=17-25;add const resolvers = { Query: { // ... your query resolvers }, Mutation: { // ... your mutation resolvers }, User: { // ... your type resolvers for `User` from before }, Post: { // ... your type resolvers for `Post` from before }, Profile: { // ... your type resolvers for `User` from before }, //add-start Category: { posts: (parent, args, context) => { return context.prisma .findUnique({ where: { id: parent.id }, }) .posts() }, }, //add-end } ``` Inside of this resolver, you're using your new `PrismaClient` to perform a query against the database. Inside the `posts` resolver, the database query loads all `Post` records from the specified `categories` (whose `id` is carried in the `parent` object). Thanks to this extra resolver, you'll now be able to nest relations in your GraphQL queries/mutations whenever you're requesting information about a `Category` type in a query. With all your type resolvers in place, you can start migrating the actual GraphQL API operations. ## 3. Migrate GraphQL operations ### 3.1. Migrate GraphQL queries In this section, you'll migrate all GraphQL _queries_ from `prisma-binding` to Prisma Client. #### 3.1.1. Migrate the `users` query (which uses `forwardTo`) In our sample API, the `users` query from the sample GraphQL schema is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Query { users(where: UserWhereInput, orderBy: Enumerable, skip: Int, after: String, before: String, first: Int, last: Int): [User]! # ... other queries } ``` ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Query: { users: forwardTo('prisma'), // ... other resolvers }, } ``` ##### Implementing the `users` resolver with Prisma Client To re-implement queries that were previously using `forwardTo`, the idea is to pass the incoming filtering, ordering and pagination arguments to `PrismaClient`: ```js const resolvers = { Query: { users: (_, args, context, info) => { // this doesn't work yet const { where, orderBy, skip, first, last, after, before } = args return context.prisma.user.findMany({ where, orderBy, skip, first, last, after, before, }) }, // ... other resolvers }, } ``` Note that this approach does **not** work yet because the _structures_ of the incoming arguments is different from the ones expected by `PrismaClient`. To ensure the structures are compatible, you can use the `@prisma/binding-argument-transform` npm package which ensures compatibility: ```copy npm install @prisma/binding-argument-transform ``` You can now use this package as follows: ```js const { makeOrderByPrisma2Compatible, makeWherePrisma2Compatible, } = require('@prisma/binding-argument-transform') const resolvers = { Query: { users: (_, args, context, info) => { // this still doesn't entirely work const { where, orderBy, skip, first, last, after, before } = args const prisma2Where = makeWherePrisma2Compatible(where) const prisma2OrderBy = makeOrderByPrisma2Compatible(orderBy) return context.prisma.user.findMany({ where: prisma2Where, orderBy: prisma2OrderBy, skip, first, last, after, before, }) }, // ... other resolvers }, } ``` The last remaining issue with this are the pagination arguments. Prisma ORM 2 introduces a [new pagination API](https://github.com/prisma/prisma/releases/tag/2.0.0-beta.7): - The `first`, `last`, `before` and `after` arguments are removed - The new `cursor` argument replaces `before` and `after` - The new `take` argument replaces `first` and `last` Here is how you can adjust the call to make it compliant with the new Prisma Client pagination API: ```js const { makeOrderByPrisma2Compatible, makeWherePrisma2Compatible, } = require('@prisma/binding-argument-transform') const resolvers = { Query: { users: (_, args, context) => { const { where, orderBy, skip, first, last, after, before } = args const prisma2Where = makeWherePrisma2Compatible(where) const prisma2OrderBy = makeOrderByPrisma2Compatible(orderBy) const skipValue = skip || 0 const prisma2Skip = Boolean(before) ? skipValue + 1 : skipValue const prisma2Take = Boolean(last) ? -last : first const prisma2Before = { id: before } const prisma2After = { id: after } const prisma2Cursor = !Boolean(before) && !Boolean(after) ? undefined : Boolean(before) ? prisma2Before : prisma2After return context.prisma.user.findMany({ where: prisma2Where, orderBy: prisma2OrderBy, skip: prisma2Skip, cursor: prisma2Cursor, take: prisma2Take, }) }, // ... other resolvers }, } ``` The calculations are needed to ensure the incoming pagination arguments map properly to the ones from the Prisma Client API. #### 3.1.2. Migrate the `posts(searchString: String): [Post!]!` query The `posts` query is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Query { posts(searchString: String): [Post!]! # ... other queries } ``` ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Query: { posts: (_, args, context, info) => { return context.prisma.query.posts( { where: { OR: [ { title_contains: args.searchString }, { content_contains: args.searchString }, ], }, }, info ) }, // ... other resolvers }, } ``` ##### Implementing the `posts` resolver with Prisma Client To get the same behavior with the new Prisma Client, you'll need to adjust your resolver implementation: ```js line-number highlight=3-11;normal const resolvers = { Query: { //highlight-start posts: (_, args, context) => { return context.prisma.post.findMany({ where: { OR: [ { title: { contains: args.searchString } }, { content: { contains: args.searchString } }, ], }, }) //highlight-end }, // ... other resolvers }, } ``` You can now send the respective query in the GraphQL Playground: ```graphql { posts { id title author { id name } } } ``` #### 3.1.3. Migrate the `user(uniqueInput: UserUniqueInput): User` query In our sample app, the `user` query is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Query { user(userUniqueInput: UserUniqueInput): User # ... other queries } input UserUniqueInput { id: String email: String } ``` ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Query: { user: (_, args, context, info) => { return context.prisma.query.user( { where: args.userUniqueInput, }, info ) }, // ... other resolvers }, } ``` ##### Implementing the `user` resolver with Prisma Client To get the same behavior with the new Prisma Client, you'll need to adjust your resolver implementation: ```js line-number highlight=3-7;normal const resolvers = { Query: { //highlight-start user: (_, args, context) => { return context.prisma.user.findUnique({ where: args.userUniqueInput, }) }, //highlight-end // ... other resolvers }, } ``` You can now send the respective query via the GraphQL Playground: ```graphql { user(userUniqueInput: { email: "alice@prisma.io" }) { id name } } ``` ### 3.1. Migrate GraphQL mutations In this section, you'll migrate the GraphQL mutations from the sample schema. #### 3.1.2. Migrate the `createUser` mutation (which uses `forwardTo`) In the sample app, the `createUser` mutation from the sample GraphQL schema is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Mutation { createUser(data: UserCreateInput!): User! # ... other mutations } ``` ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Mutation: { createUser: forwardTo('prisma'), // ... other resolvers }, } ``` ##### Implementing the `createUser` resolver with Prisma Client To get the same behavior with the new Prisma Client, you'll need to adjust your resolver implementation: ```js line-number highlight=3-7;normal const resolvers = { Mutation: { //highlight-start createUser: (_, args, context, info) => { return context.prisma.user.create({ data: args.data, }) }, //highlight-end // ... other resolvers }, } ``` You can now write your first mutation against the new API, e.g.: ```graphql mutation { createUser(data: { name: "Alice", email: "alice@prisma.io" }) { id } } ``` #### 3.1.3. Migrate the `createDraft(title: String!, content: String, authorId: String!): Post!` query In the sample app, the `createDraft` mutation is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Mutation { createDraft(title: String!, content: String, authorId: String!): Post! # ... other mutations } ``` ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Mutation: { createDraft: (_, args, context, info) => { return context.prisma.mutation.createPost( { data: { title: args.title, content: args.content, author: { connect: { id: args.authorId, }, }, }, }, info ) }, // ... other resolvers }, } ``` ##### Implementing the `createDraft` resolver with Prisma Client To get the same behavior with the new Prisma Client, you'll need to adjust your resolver implementation: ```js line-number highlight=3-15;normal const resolvers = { Mutation: { //highlight-start createDraft: (_, args, context, info) => { return context.prisma.post.create({ data: { title: args.title, content: args.content, author: { connect: { id: args.authorId, }, }, }, }) }, //highlight-end // ... other resolvers }, } ``` You can now send the respective mutation via the GraphQL Playground: ```graphql mutation { createDraft(title: "Hello World", authorId: "__AUTHOR_ID__") { id published author { id name } } } ``` #### 3.1.4. Migrate the `updateBio(bio: String, userUniqueInput: UserUniqueInput!): User` mutation In the sample app, the `updateBio` mutation is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Mutation { updateBio(bio: String!, userUniqueInput: UserUniqueInput!): User # ... other mutations } ``` ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Mutation: { updateBio: (_, args, context, info) => { return context.prisma.mutation.updateUser( { data: { profile: { update: { bio: args.bio }, }, }, where: { id: args.userId }, }, info ) }, // ... other resolvers }, } ``` ##### Implementing the `updateBio` resolver with Prisma Client To get the same behavior with Prisma Client, you'll need to adjust your resolver implementation: ```js line-number highlight=3-12;normal const resolvers = { Mutation: { //highlight-start updateBio: (_, args, context, info) => { return context.prisma.user.update({ data: { profile: { update: { bio: args.bio }, }, }, where: args.userUniqueInput, }) }, //highlight-end // ... other resolvers }, } ``` You can now send the respective mutation via the GraphQL Playground : ```graphql mutation { updateBio( userUniqueInput: { email: "alice@prisma.io" } bio: "I like turtles" ) { id name profile { id bio } } } ``` #### 3.1.5. Migrate the `addPostToCategories(postId: String!, categoryIds: [String!]!): Post` mutation In our sample app, the `addPostToCategories` mutation is defined and implemented as follows. ##### SDL schema definition with `prisma-binding` ```graphql type Mutation { addPostToCategories(postId: String!, categoryIds: [String!]!): Post # ... other mutations } ``` ##### Resolver implementation with `prisma-binding` ```js const resolvers = { Mutation: { addPostToCategories: (_, args, context, info) => { const ids = args.categoryIds.map((id) => ({ id })) return context.prisma.mutation.updatePost( { data: { categories: { connect: ids, }, }, where: { id: args.postId, }, }, info ) }, // ... other resolvers }, } ``` ##### Implementing the `addPostToCategories` resolver with Prisma Client To get the same behavior with Prisma Client, you'll need to adjust your resolver implementation: ```js line-number highlight=3-13;normal const resolvers = { Mutation: { //highlight-start addPostToCategories: (_, args, context, info) => { const ids = args.categoryIds.map((id) => ({ id })) return context.prisma.post.update({ where: { id: args.postId, }, data: { categories: { connect: ids }, }, }) }, //highlight-end // ... other resolvers }, } ``` You can now send the respective query via the GraphQL Playground: ```graphql mutation { addPostToCategories( postId: "__AUTHOR_ID__" categoryIds: ["__CATEGORY_ID_1__", "__CATEGORY_ID_2__"] ) { id title categories { id name } } } ``` ## 4. Cleaning up Since the entire app has now been upgraded to Prisma ORM 2, you can delete all unnecessary files and remove the no longer needed dependencies. ### 4.1. Clean up npm dependencies You can start by removing npm dependencies that were related to the Prisma 1 setup: ```copy npm uninstall graphql-cli prisma-binding prisma1 ``` ### 4.2. Delete unused files Next, delete the files of your Prisma 1 setup: ```copy rm prisma1/datamodel.prisma prisma1/prisma.yml ``` ### 4.3. Stop the Prisma ORM server Finally, you can stop running your Prisma ORM server. --- # REST API URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-a-rest-api ## Overview This upgrade guide describes how to migrate a Node.js project that's based on [Prisma 1](https://github.com/prisma/prisma1) and uses the [Prisma 1 client](https://v1.prisma.io/docs/1.34/prisma-client/) to implement a REST API. The guide assumes that you already went through the [guide for upgrading the Prisma ORM layer](/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrading-the-prisma-layer-postgresql). This means you already: - installed the Prisma ORM 2 CLI - created your Prisma ORM 2 schema - introspected your database and resolved potential schema incompatibilities - installed and generated Prisma Client The guide further assumes that you have a file setup that looks similar to this: ``` . ├── README.md ├── package-lock.json ├── package.json ├── prisma │ ├── datamodel.prisma │ ├── docker-compose-mysql.yml │ ├── docker-compose.yml │ ├── prisma.yml │ └── seed.graphql ├── src │ ├── generated │ │ └── prisma-client │ │ ├── index.ts │ │ └── prisma-schema.ts │ └── index.ts └── tsconfig.json ``` The important parts are: - A folder called with `prisma` with your Prisma ORM 2 schema - A folder called `src` with your application code If this is not what your project structure looks like, you'll need to adjust the instructions in the guide to match your own setup. ## 1. Adjust the application to use Prisma Client 2 For the purpose of this guide, we'll use the sample API calls from the [`express`](https://github.com/prisma/prisma1-examples/tree/master/typescript/rest-express) example in the [`prisma1-examples`](https://github.com/prisma/prisma1-examples/) repository. The application code in our example is located in a single file and looks as follows: ```ts import * as express from 'express' import * as bodyParser from 'body-parser' import { prisma } from './generated/prisma-client' const app = express() app.$use(bodyParser.json()) app.post(`/user`, async (req, res) => { const result = await prisma.createUser({ ...req.body, }) res.json(result) }) app.post(`/post`, async (req, res) => { const { title, content, authorEmail } = req.body const result = await prisma.createPost({ title: title, content: content, author: { connect: { email: authorEmail } }, }) res.json(result) }) app.put('/publish/:id', async (req, res) => { const { id } = req.params const post = await prisma.updatePost({ where: { id }, data: { published: true }, }) res.json(post) }) app.delete(`/post/:id`, async (req, res) => { const { id } = req.params const post = await prisma.deletePost({ id }) res.json(post) }) app.get(`/post/:id`, async (req, res) => { const { id } = req.params const post = await prisma.post({ id }) res.json(post) }) app.get('/feed', async (req, res) => { const posts = await prisma.post({ where: { published: true } }) res.json(posts) }) app.get('/filterPosts', async (req, res) => { const { searchString } = req.query const draftPosts = await prisma.post({ where: { OR: [ { title_contains: searchString, }, { content_contains: searchString, }, ], }, }) res.json(draftPosts) }) app.listen(3000, () => console.log('Server is running on http://localhost:3000') ) ``` Consider each occurrence of the Prisma Client instance `prisma` and replacing with the respective usage of Prisma Client 2. You can learn more in the [API Reference](/orm/prisma-client). ### 1.1. Adjusting the import Import the generated `@prisma/client` node module as shown: ```ts import { PrismaClient } from '@prisma/client' ``` Note that this only imports the `PrismaClient` constructor, so you also need to instantiate a Prisma Client 2 instance: ```ts const prisma = new PrismaClient() ``` ### 1.2. Adjusting the `/user` route (`POST`) With the Prisma Client 2 API, the `/user` route for `POST` requests has to be changed to: ```ts app.post(`/user`, async (req, res) => { const result = await prisma.user.create({ data: { ...req.body, }, }) res.json(result) }) ``` ### 1.3. Adjusting the `/post` route (`POST`) With the Prisma Client 2 API, the `/post` route for `POST` requests has to be changed to: ```ts app.post(`/post`, async (req, res) => { const { title, content, authorEmail } = req.body const result = await prisma.post.create({ data: { title: title, content: content, author: { connect: { email: authorEmail } }, }, }) res.json(result) }) ``` ### 1.4. Adjusting the `/publish/:id` route (`PUT`) With the Prisma Client 2 API, the `/publish/:id` route for `PUT` requests has to be changed to: ```ts app.put('/publish/:id', async (req, res) => { const { id } = req.params const post = await prisma.post.update({ where: { id }, data: { published: true }, }) res.json(post) }) ``` ### 1.5. Adjusting the `/post/:id` route (`DELETE`) With the Prisma Client 2 API, the `//post/:id` route for `DELETE` requests has to be changed to: ```ts app.delete(`/post/:id`, async (req, res) => { const { id } = req.params const post = await prisma.post.delete({ where: { id }, }) res.json(post) }) ``` ### 1.6. Adjusting the `/post/:id` route (`GET`) With the Prisma Client 2 API, the `/post/:id` route for `GET` requests has to be changed to: ```ts app.get(`/post/:id`, async (req, res) => { const { id } = req.params const post = await prisma.post.findUnique({ where: { id }, }) res.json(post) }) ``` ### 1.7. Adjusting the `/feed` route (`GET`) With the Prisma Client 2 API, the `/feed` route for `GET` requests has to be changed to: ```ts app.get('/feed', async (req, res) => { const posts = await prisma.post.findMany({ where: { published: true } }) res.json(posts) }) ``` ### 1.8. Adjusting the `/filterPosts` route (`GET`) With the Prisma Client 2 API, the `/user` route for `POST` requests has to be changed to: ```ts app.get('/filterPosts', async (req, res) => { const { searchString } = req.query const filteredPosts = await prisma.post.findMany({ where: { OR: [ { title: { contains: searchString }, }, { content: { contains: searchString }, }, ], }, }) res.json(filteredPosts) }) ``` --- # Upgrade from MongoDB Beta URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrade-from-prisma-1/upgrade-from-mongodb-beta ## Introduction This guide helps you migrate from the Prisma 1 MongoDB Beta to MongoDB on Prisma ORM 2 or later. To learn more about the differences between Prisma 1 and Prisma ORM 2.x and later, refer to [this document](/orm/more/upgrade-guides/upgrade-from-prisma-1/how-to-upgrade#main-differences-between-prisma-1-and-prisma-orm-version-2x-and-later). The scope of this guide is to give you the workflow necessary to perform the migration and highlight some of the problems you might encounter. We unfortunately can't cover all possible scenarios or changes required, but this guide should help you on your journey. Join [our Discord](https://pris.ly/discord?utm_source=docs&utm_medium=intro_text) or create an issue [on Github](https://github.com/prisma/prisma1/issues/new/choose) with any questions. Perform this migration on your staging environment before trying this in production! ## Requirements - Must be running MongoDB 4.2+ as a replica set (MongoDB Atlas does this for you automatically) - Node.js: see [system requirements](/orm/reference/system-requirements) - TypeScript: see [system requirements](/orm/reference/system-requirements) ## Installing Prisma ORM 3.12.0 or later In your project directory run the following commands: ```bash $ npm install prisma@latest $ npx prisma init --datasource-provider=mongodb ``` This should create the following files: - `prisma/schema.prisma`: An initial Prisma schema - `.env`: Environment file where you'll store your connection string If you see the following error: ``` ERROR File schema.prisma already exists in your project. Please try again in a project that is not yet using Prisma. ``` You have likely a `prisma/` directory in your project already. Rename that directory to something like `_prisma/` and try again ## Find the Connection String to your MongoDB Database Next you'll want to find the connection string to your MongoDB database. You should be able to find it in your `docker-compose.yml` file or on MongoDB Atlas. It's what you'd pass to MongoDB Compass. The connection string should look something like this: ```bash mongodb://:@:27017 ``` The database that stores application data in Prisma 1 is called `default_default`, so we'll add that to the end of the connection string and update the `DATABASE_URL` key in the `.env` file ```bash file=.env DATABASE_URL="mongodb://prisma:prisma@localhost:27017/default_default" ``` ## Introspect your MongoDB Database You're now ready to pull the structure of your database down into your Prisma Schema. ```bash $ npx prisma db pull ``` And you should see your Prisma schema in `prisma/schema.prisma` populated with your models. If you see the following error: `Error in connector: SCRAM failure: Authentication failed.`, try adding `?authSource=admin` to the end of your connection string and trying again. ## Touching up your Prisma Schema The generated Prisma Client from a freshly introspected Prisma 1 based MongoDB database may not have the best API. You can adjust the model names and fields, just be sure to `@map` and `@@map` the original name to the underlying database collection and field names: ```diff - model posts { + model Post { id String @id @default(auto()) @map("_id") @db.ObjectId published Boolean title String + @@map("posts") } - model users { + model User { id String @id @default(auto()) @map("_id") @db.ObjectId email String @unique(map: "email_U") name String - posts String[] @db.ObjectId + postIds String[] @db.ObjectId @map("posts") @@index([posts], map: "posts_R") + @@map("users") } ``` Take caution in doing these renames because you need to make sure the Prisma Schema still maps properly to the underlying database collections and field names. Unlike SQL databases, MongoDB doesn't have an explicit understanding of relationships between data. This means that Prisma ORM's introspection is unable to infer those relationships for you. We typically recommend adding the relationships by hand with the help of [this documentation](/orm/overview/databases/mongodb#how-to-add-in-missing-relations-after-introspection). However, Prisma 1 stores foreign keys is different than where Prisma ORM 2 and later expects foreign keys, so if you want to take advantage of relationships, you'll need to shift where the foreign keys are on your database before adding the relationships. 💡 Download the Prisma VSCode Extension to provide autocomplete and helpful error messages as you transition your Prisma schema. ## Generating a Prisma Client With the Prisma schema populated with the schema of your data, you're now ready to generate a Typescript Client to read and write to your MongoDB database. ```bash $ npx prisma generate ``` ## Testing Reads Create a simple `test.ts` script to verify that Prisma Client can read and write to your application. Note that this guide is using the example in the [Prisma 1 examples repository](https://github.com/prisma/prisma1-examples/tree/master/typescript/docker-mongodb), but the code will change depending on your application. ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { await prisma.$connect() const posts = await prisma.post.findMany() console.log(posts) } main() .catch(console.error) .finally(() => prisma.$disconnect()) ``` Make sure `ts-node` is installed globally and run: ```bash ts-node test.ts ``` You should see a list of your data: ```bash [ { comments: [], id: '62435a83fca136000996ba16', content: 'https://www.prisma.io/day/', published: true, title: 'Join us for Prisma Day 2019 in Berlin', wasCreated: 2022-03-29T19:14:11.172Z, wasUpdated: 2022-03-29T19:14:11.172Z }, { comments: [ [Object] ], id: '62435a83fca136000996ba18', content: 'https://graphqlweekly.com/', published: true, title: 'Subscribe to GraphQL Weekly for community news', wasCreated: 2022-03-29T19:14:11.369Z, wasUpdated: 2022-03-29T19:14:11.369Z }, { comments: [], id: '62435a83fca136000996ba1a', content: 'https://twitter.com/prisma', published: false, title: 'Follow Prisma on Twitter', wasCreated: 2022-03-29T19:14:11.375Z, wasUpdated: 2022-03-29T19:14:11.375Z } ] ``` ## Testing Writes You can then alter your `test.ts` to try writes: ```ts import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { await prisma.$connect() const user = await prisma.user.create({ data: { email: 'alice@prisma.io', name: 'Alice', }, }) console.log(user) } main() .catch(console.error) .finally(() => prisma.$disconnect()) ``` And you should see a user was created. If you see the following error: ```no-lines wrap Prisma needs to perform transactions, which requires your MongoDB server to be run as a replica set. https://pris.ly/d/mongodb-replica-set ``` This means that your MongoDB database isn't running as a replica set. Refer to [the link above](https://pris.ly/d/mongodb-replica-set) for steps to resolve this issue. ## Upgrading your Application Now that you have a working Prisma Client, you can start replacing Prisma Client 1 queries with the latest Prisma Client queries. The [Prisma Client Reference](/orm/reference/prisma-client-reference#filter-conditions-and-operators) is a helpful resource for learning how to use the latest Prisma Client. ## Conclusion I hope this brief guide was helpful in getting you started on the right path. Let us know if you have any questions or issues. We really appreciate your support over the years. --- # Upgrade from Prisma 1 URL: https://www.prisma.io/docs/orm/more/upgrade-guides/upgrade-from-prisma-1/index ## In this section --- # Upgrade guides URL: https://www.prisma.io/docs/orm/more/upgrade-guides/index ## In this section --- # Cursor URL: https://www.prisma.io/docs/orm/more/ai-tools/cursor [Cursor](https://www.cursor.com/) is an AI-powered code editor designed to boost productivity by automating repetitive coding tasks. When paired with Prisma, a robust and type-safe toolkit for database workflows, it becomes a powerful solution for managing and optimizing database schemas, queries, and data seeding. This guide provides detailed instructions for effectively using Prisma with Cursor to: - Define project-specific best practices with `.cursorrules`. - Using Cursor's context-aware capabilities. - Generate schemas, queries, and seed data tailored to your database. :::note While this guide is focused on Cursor, these patterns should work with any AI editor. [Let us know on X](https://pris.ly/x?utm_source=docs&utm_medium=inline_text) if you'd like us to create guides for your preferred tool! ::: ## Prisma MCP server Prisma provides its own [Model Context Protocol](https://modelcontextprotocol.io/introduction) (MCP) server that lets you manage Prisma Postgres databases, model database schemas and chat through migrations. Learn more about how you can add it to Cursor [here](/postgres/mcp-server#cursor). ## Defining project-specific rules with `.cursorrules` The [`.cursorrules` file](https://docs.cursor.com/context/rules-for-ai#cursorrules) in Cursor allows you to enforce best practices and development standards tailored to your Prisma projects. By defining clear and consistent rules, you can ensure that Cursor generates clean, maintainable, and project-specific code with minimal manual adjustments. To implement these rules, create a `.cursorrules` file in the root of your project. Below is an example configuration:
Example `.cursorrules` file ```text file=.cursorrules You are a senior TypeScript/JavaScript programmer with expertise in Prisma, clean code principles, and modern backend development. Generate code, corrections, and refactorings that comply with the following guidelines: TypeScript General Guidelines Basic Principles - Use English for all code and documentation. - Always declare explicit types for variables and functions. - Avoid using "any". - Create precise, descriptive types. - Use JSDoc to document public classes and methods. - Maintain a single export per file. - Write self-documenting, intention-revealing code. Nomenclature - Use PascalCase for classes and interfaces. - Use camelCase for variables, functions, methods. - Use kebab-case for file and directory names. - Use UPPERCASE for environment variables and constants. - Start function names with a verb. - Use verb-based names for boolean variables: - isLoading, hasError, canDelete - Use complete words, avoiding unnecessary abbreviations. - Exceptions: standard abbreviations like API, URL - Accepted short forms: - i, j for loop indices - err for errors - ctx for contexts Functions - Write concise, single-purpose functions. - Aim for less than 20 lines of code. - Name functions descriptively with a verb. - Minimize function complexity: - Use early returns. - Extract complex logic to utility functions. - Leverage functional programming techniques: - Prefer map, filter, reduce. - Use arrow functions for simple operations. - Use named functions for complex logic. - Use object parameters for multiple arguments. - Maintain a single level of abstraction. Data Handling - Encapsulate data in composite types. - Prefer immutability. - Use readonly for unchanging data. - Use as const for literal values. - Validate data at the boundaries. Error Handling - Use specific, descriptive error types. - Provide context in error messages. - Use global error handling where appropriate. - Log errors with sufficient context. Prisma-Specific Guidelines Schema Design - Use meaningful, domain-driven model names. - Leverage Prisma schema features: - Use @id for primary keys. - Use @unique for natural unique identifiers. - Utilize @relation for explicit relationship definitions. - Keep schemas normalized and DRY. - Use meaningful field names and types. - Implement soft delete with deletedAt timestamp. - Use Prisma's native type decorators. Prisma Client Usage - Always use type-safe Prisma client operations. - Prefer transactions for complex, multi-step operations. - Use Prisma middleware for cross-cutting concerns: - Logging - Soft delete - Auditing - Handle optional relations explicitly. - Use Prisma's filtering and pagination capabilities. Database Migrations - Create migrations for schema changes. - Use descriptive migration names. - Review migrations before applying. - Never modify existing migrations. - Keep migrations idempotent. Error Handling with Prisma - Catch and handle Prisma-specific errors: - PrismaClientKnownRequestError - PrismaClientUnknownRequestError - PrismaClientValidationError - Provide user-friendly error messages. - Log detailed error information for debugging. Testing Prisma Code - Use in-memory database for unit tests. - Mock Prisma client for isolated testing. - Test different scenarios: - Successful operations - Error cases - Edge conditions - Use factory methods for test data generation. - Implement integration tests with actual database. Performance Considerations - Use select and include judiciously. - Avoid N+1 query problems. - Use findMany with take and skip for pagination. - Leverage Prisma's distinct for unique results. - Profile and optimize database queries. Security Best Practices - Never expose raw Prisma client in APIs. - Use input validation before database operations. - Implement row-level security. - Sanitize and validate all user inputs. - Use Prisma's built-in protections against SQL injection. Coding Style - Keep Prisma-related code in dedicated repositories/modules. - Separate data access logic from business logic. - Create repository patterns for complex queries. - Use dependency injection for Prisma services. Code Quality - Follow SOLID principles. - Prefer composition over inheritance. - Write clean, readable, and maintainable code. - Continuously refactor and improve code structure. Development Workflow - Use version control (Git). - Implement comprehensive test coverage. - Use continuous integration. - Perform regular code reviews. - Keep dependencies up to date. ```
This file ensures consistent and maintainable code generation, reducing manual intervention while improving project quality. ## Using Cursor's context-aware capabilities Cursor's [context-aware](https://docs.cursor.com/context/) capabilities let you add specific websites, files, folders or documentation to enhance its understanding of your project. By adding your `schema.prisma` file as context, you enable Cursor to generate more accurate queries, tests, and seed data based on your database schema. ### Add Prisma docs `llm.txt` file as `@Docs` context To improve Cursor's understanding of Prisma-related suggestions in your project, include the [`/llms.txt`](https://llmstxt.org/) markdown file as context. This file offers a concise overview, useful guidance, and links to detailed Prisma documentation—all optimized for LLM processing. Simply navigate to the [url](https://pris.ly/llms.txt) and add it as a `@Docs` resource in your Cursor configuration. ### Adding additional Prisma documentation Cursor already includes built-in context from Prisma documentation, so you don't need to add anything to make us of our docs! You can view the existing resources Cursor uses [here](https://raw.githubusercontent.com/getcursor/crawler/main/docs.jsonl). To stay updated with the latest changes or incorporate additional context, add these resources as `@Docs` context: - [Prisma Changelog](https://www.prisma.io/changelog) for updates and new features. - [Prisma Blog](https://www.prisma.io/blog) for practical guides and best practices. To learn how to add and manage documentation context, visit the [Cursor documentation](https://docs.cursor.com/context/@-symbols/@-docs#docs). ### Using schema as context Add your `schema.prisma` file (or the entire codebase) as context using the [`@Files`](https://docs.cursor.com/context/@-symbols/@-files) syntax before requesting queries, tests, or seed scripts. This allows Cursor to generate precise, schema-driven outputs such as queries, tests, and seed data. For example, in [Cursor Chat](https://docs.cursor.com/chat/overview), you can include your schema by typing `@Files` followed by adding your `schema.prisma` file. ## Generating Prisma Schema Cursor can generate Prisma schemas from high-level descriptions, enabling you to quickly establish a solid foundation for your database schema. By providing a clear and detailed prompt, Cursor creates Prisma schemas tailored to your requirements. Whether you need a general foundational schema or a highly specific one for detailed use cases, Cursor can deliver with precision. Here's an example prompt and its corresponding result: :::note If you run the prompts below, you may receive a different outputs because LLMs produce non-deterministic responses. ::: ```text copy "Create a Prisma schema for a SaaS app using PostgreSQL as a provider with `User`, `Organization`, and `Subscription` models, ensuring all models include `createdAt` and `updatedAt` DateTime fields with defaults, a soft-delete `deletedAt` field, and proper relationships between entities." ``` ```prisma file=schema.prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) email String @unique name String password String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime? organization Organization @relation(fields: [organizationId], references: [id]) organizationId Int role UserRole @default(MEMBER) } model Organization { id Int @id @default(autoincrement()) name String slug String @unique subscription Subscription? users User[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime? } model Subscription { id Int @id @default(autoincrement()) organization Organization @relation(fields: [organizationId], references: [id]) organizationId Int @unique plan SubscriptionPlan status SubscriptionStatus @default(ACTIVE) startDate DateTime endDate DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime? } enum UserRole { ADMIN MEMBER } enum SubscriptionPlan { FREE BASIC PREMIUM ENTERPRISE } enum SubscriptionStatus { ACTIVE CANCELED EXPIRED PAST_DUE } ``` ## Generating Prisma queries Cursor can help you create queries tailored to your Prisma schema, whether for basic data retrieval or complex, optimized operations. To get the best results, focus on writing clear, specific prompts that define your requirements, such as the fields to include, conditions to apply, and relationships to traverse. This ensures Cursor generates accurate, performant, and type-safe queries. Here's an example prompt and its resulting query: ```text copy "Generate a query to retrieve all User records associated with an Organization that has an `active` Subscription, while excluding any records where the deletedAt field is set." ``` ```typescript const activeUsers = await prisma.user.findMany({ where: { deletedAt: null, organization: { deletedAt: null, subscription: { deletedAt: null, status: 'ACTIVE' } } }, include: { organization: { include: { subscription: true } } }, orderBy: { createdAt: 'desc' }, skip: 0, take: 10 }); ``` ## Creating seed files with Cursor Writing seed scripts can be a tedious process, but Cursor simplifies it by quickly generating structured and organized seed code. By providing clear instructions, you can guide Cursor to create scripts that populate your database with realistic data, including handling relationships and complex structures defined in your schema. Here's an example prompt and its resulting seed script: ```text copy "Generate code to populate the Prisma schema with realistic data for the User, Organization, and Subscription models, ensuring all necessary fields are included." ``` ```ts file=seed.ts import { PrismaClient, UserRole, SubscriptionPlan, SubscriptionStatus, } from "@prisma/client"; const prisma = new PrismaClient(); async function main() { // Clear existing data await prisma.user.deleteMany(); await prisma.subscription.deleteMany(); await prisma.organization.deleteMany(); const organizations = [ { name: "Tech Innovators", slug: "tech-innovators", subscription: { plan: SubscriptionPlan.ENTERPRISE, status: SubscriptionStatus.ACTIVE, startDate: new Date("2024-01-01"), }, users: [ { name: "Emma Thompson", email: "emma@techinnovators.com", role: UserRole.ADMIN, password: "password123", }, { name: "Michael Chen", email: "michael@techinnovators.com", role: UserRole.MEMBER, password: "password123", }, ], }, { name: "Digital Solutions", slug: "digital-solutions", subscription: { plan: SubscriptionPlan.PREMIUM, status: SubscriptionStatus.ACTIVE, startDate: new Date("2024-01-15"), }, users: [ { name: "Sarah Wilson", email: "sarah@digitalsolutions.com", role: UserRole.ADMIN, password: "password123", }, { name: "James Miller", email: "james@digitalsolutions.com", role: UserRole.MEMBER, password: "password123", }, ], }, { name: "Cloud Systems", slug: "cloud-systems", subscription: { plan: SubscriptionPlan.BASIC, status: SubscriptionStatus.ACTIVE, startDate: new Date("2024-02-01"), }, users: [ { name: "David Garcia", email: "david@cloudsystems.com", role: UserRole.ADMIN, password: "password123", }, { name: "Lisa Wang", email: "lisa@cloudsystems.com", role: UserRole.MEMBER, password: "password123", }, ], }, { name: "Data Analytics Co", slug: "data-analytics", subscription: { plan: SubscriptionPlan.PREMIUM, status: SubscriptionStatus.ACTIVE, startDate: new Date("2024-01-10"), }, users: [ { name: "Alex Johnson", email: "alex@dataanalytics.com", role: UserRole.ADMIN, password: "password123", }, { name: "Rachel Kim", email: "rachel@dataanalytics.com", role: UserRole.MEMBER, password: "password123", }, ], }, { name: "Smart Solutions", slug: "smart-solutions", subscription: { plan: SubscriptionPlan.FREE, status: SubscriptionStatus.ACTIVE, startDate: new Date("2024-02-15"), }, users: [ { name: "Daniel Brown", email: "daniel@smartsolutions.com", role: UserRole.ADMIN, password: "password123", }, { name: "Maria Rodriguez", email: "maria@smartsolutions.com", role: UserRole.MEMBER, password: "password123", }, ], }, ]; for (const org of organizations) { const createdOrg = await prisma.organization.create({ data: { name: org.name, slug: org.slug, subscription: { create: { plan: org.subscription.plan, status: org.subscription.status, startDate: org.subscription.startDate, }, }, }, }); for (const user of org.users) { await prisma.user.create({ data: { name: user.name, email: user.email, password: user.password, role: user.role, organizationId: createdOrg.id, }, }); } } console.log("Seed data created successfully"); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); }); ``` ## Additional resources In summary, using Cursor with Prisma simplifies your workflow, from generating schemas and queries to writing seed scripts. By following this guide, you can save time, reduce errors, and focus on building your application. Learn more about Cursor in their [official documentation](https://docs.cursor.com/context/@-symbols/basic). --- # Tabnine URL: https://www.prisma.io/docs/orm/more/ai-tools/tabnine [Tabnine](https://www.tabnine.com/) is a an AI software development platform that comes as an [extension](https://www.tabnine.com/install/) for your IDE (e.g. VS Code, WebStorm, IntelliJ, ...). ## Overview It helps developers write code faster by: - Providing context-aware [code completion](https://docs.tabnine.com/main/getting-started/getting-the-most-from-tabnines-code-completion) suggestions in the editor for small, repetitive coding tasks - Offering an integrated [chat](https://docs.tabnine.com/main/getting-started/getting-the-most-from-tabnine-chat) for higher-level tasks and detailed instructions ### Why use Prisma ORM with Tabnine? AI editors like Tabnine are powerful tools that can drastically improve developer productivity. It works especially well with the following workflows: - Data modeling and database schema design - Constructing and optimizing database queries - Generating CRUD functionality and other boilerplate code - Generating plain SQL queries that can be used with [TypedSQL](/orm/prisma-client/using-raw-sql/typedsql) - Generating code for unit and integrations tests - Guiding through major refactorings - Generating seeding scripts ### Leveraging the Prisma schema Because Prisma has its own [schema](/orm/prisma-schema), Tabnine can understand the basic shape of your data and help you write code for the other parts of your stack. We therefore recommend that you start out by defining your Prisma schema and then use Tabnine to build the application layer around it (inluding API calls, DTOs, business logic, 3rd party integrations, ...). ## Data modeling and database schema design ### How Tabnine helps Designing a database schema from scratch involves a lot of boilerplate and can be time-consuming. Tabnine can accelerate this process by: - Generating boilerplate for models, indexes, constraints, and relations. - Keeping the schema consistent by sticking to naming and other conventions. - Auto-completing model and field definitions based on common database patterns. - Suggesting relationships and field types based on naming conventions. ### Example: Defining a Prisma schema #### Prompt _Define a Prisma schema for a SaaS application with User, Organization, and Subscription models. Ensure relationships are properly set up._ #### Generated code ```prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt email String @unique name String organization Organization @relation(fields: [organizationId], references: [id]) organizationId Int } model Organization { id Int @id @default(autoincrement()) name String slug String @unique subscription Subscription? users User[] } model Subscription { id Int @id @default(autoincrement()) organization Organization @relation(fields: [organizationId], references: [id]) organizationId Int @unique plan String status Status } enum Status { Active Paused Expired } ``` ## Constructing and optimizing database queries ### How Tabnine helps Prisma ORM provides a convenient high-level API for writing database queries intuitively. However, queries involving filters, pagination and advanced patterns can still become complex to construct. Tabnine can help by: - Auto-completing Prisma queries based on the schema. - Suggesting `where` clauses for filters and `skip` / `take` options for pagination logic. - Helping with efficiency and performance optimizations. ### Example: fetching data with relationships #### Prompt _Generate a Prisma query to fetch all active users from an organization with an active subscription. Include data about the users' organizations in the query result._ #### Generated code ```ts const activeUsers = await prisma.user.findMany({ where: { organization: { subscription: { status: "ACTIVE" } } }, include: { organization: true } }); ``` ## Generating CRUD functionality and other boilerplate code ### How Tabnine helps Most applications require basic CRUD operations or other boilerplate code that's usually derived from the structure of the database schema. For example, an API layer may expose a set of HTTP endpoints that allow to create, read, update or delete records of a certain model. Similarly, a frontend will data fetching and state management logic to interact with these API endpoints and update the UI accordingly. Instead of writing this code manually, Tabnine can speed up this process by: - Generating Prisma `create`, `read`, `update`, and `delete` operations for the backend and UI components for the frontend. - Auto-completing function names and argument types. - Write boilerplate code while following best practices for using DTOs, error handling, consistent API design, ... ### Example: Generating CRUD functionality with Next.js #### Prompt _Generate CRUD functionality for a Next.js app based on the User model from the schema above._ #### Generated code ##### API endpoints ```ts filename=app/api/users/routes.ts import { NextResponse } from 'next/server'; import prisma from '../../../lib/prisma'; export async function GET() { const users = await prisma.user.findMany({ include: { organization: true }, }); return NextResponse.json(users); } export async function POST(request: Request) { const body = await request.json(); const user = await prisma.user.create({ data: { email: body.email, name: body.name, organization: { connect: { id: body.organizationId }, }, }, include: { organization: true }, }); return NextResponse.json(user); } export async function PUT(request: Request) { const body = await request.json(); const user = await prisma.user.update({ where: { id: body.id }, data: { email: body.email, name: body.name, organizationId: body.organizationId, }, include: { organization: true }, }); return NextResponse.json(user); } export async function DELETE(request: Request) { const { searchParams } = new URL(request.url); const id = searchParams.get('id'); const user = await prisma.user.delete({ where: { id: Number(id) }, }); return NextResponse.json(user); } ``` ##### React components ```ts filename=app/components/User.tsx import React, { useState, useEffect } from 'react'; interface User { id: number; email: string; name: string; organizationId: number; } const User: React.FC = () => { const [users, setUsers] = useState([]); const [newUser, setNewUser] = useState({ email: '', name: '', organizationId: 0 }); useEffect(() => { fetchUsers(); }, []); const fetchUsers = async () => { const response = await fetch('/api/users'); const data = await response.json(); setUsers(data); }; const createUser = async () => { await fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newUser), }); fetchUsers(); setNewUser({ email: '', name: '', organizationId: 0 }); }; const deleteUser = async (id: number) => { await fetch(`/api/users?id=${id}`, { method: 'DELETE' }); fetchUsers(); }; return (

Users

    {users.map((user) => (
  • {user.name} ({user.email}) - Org ID: {user.organizationId}
  • ))}

Create New User

setNewUser({ ...newUser, name: e.target.value })} /> setNewUser({ ...newUser, email: e.target.value })} /> setNewUser({ ...newUser, organizationId: Number(e.target.value) })} />
); }; export default User; ``` ## Generating plain SQL queries for use with TypedSQL ### How Tabnine helps While Prisma provides a high-level API for querying, sometimes a developer may need to drop down to raw SQL for more low-level control of a query. In these cases, they can use [TypedSQL](/orm/prisma-client/using-raw-sql/typedsql) which provides full type safety for raq SQL queries in Prisma ORM. One common use case are aggregation queries, such as calculating percentages of different subscription statuses in the schema example above. Tabnine can assist by: - Generating SQL queries based on your Prisma schema. - Structuring complex aggregations without manual trial and error. - Integrating the queries in your application code. ### Example: Calculating the percentages of active, expired, and paused subscriptions #### Prompt _Generate a SQL query that returns the percentage of subscriptions that are Active, Paused, and Expired._ #### Generated SQL query ```sql file=prisma/sql/subscriptionsReport.sql SELECT status, COUNT(*) * 100.0 / (SELECT COUNT(*) FROM "Subscription") AS percentage FROM "Subscription" GROUP BY status; ``` #### Application code ```ts import { PrismaClient } from '@prisma/client' import { subscriptionsReport } from '@prisma/client/sql' const prisma = new PrismaClient(); const usersWithPostCounts = await prisma.$queryRawTyped(subscriptionsReport()) console.log(usersWithPostCounts) ``` ## Generating code for unit and integration tests ### How Tabnine helps Writing tests ensures that Prisma-based applications function correctly and behave according to requirements and expectations. However, writing tests is a time-consuming activity that often follows predictable and repetitive patterns. Tabnine can drastically speed up writing tests by: - Generating test boilerplate for both unit and integration tests. - Suggesting mocks and fixtures for Prisma database interactions. - Helping structure test cases to follow best practices. - Providing integration test scaffolding for testing Prisma with a real or in-memory database. ### Example: Writing a unit test for a Prisma service #### Prompt _Generate a Jest unit test for a Prisma service function that fetches all active users._ #### Generated code ```ts filename=__tests__/userService.test.ts import { prismaMock } from '../prisma/singleton'; import { getActiveUsers } from '../services/userService'; test('should return only active users', async () => { prismaMock.user.findMany.mockResolvedValue([ { id: 1, name: 'Alice', email: 'alice@example.com' }, { id: 2, name: 'Bob', email: 'bob@example.com' } ]); const users = await getActiveUsers(); expect(users).toHaveLength(2); expect(users[0].email).toBe('alice@example.com'); }); ``` ## Guiding through major refactorings ### How Tabnine helps Thanks to Prisma ORM's type safe queries, refactoring are more safe and predictable than with other ORMs: After making schema changes, the generated Prisma Client code will be updated and the TypeScript compiler will highlight all places that need a change. However, there may still be more difficult situations during a refactoring, e.g. when business logic or complex queries need to be adjusted. Tabnine can assist during refactorings by: - Identifying patterns in your code and suggesting refactorings while maintaining consistency. - Helping update database queries after schema changes and reducing manual effort. - Providing function rewrites to simplify and optimize logic. - Suggesting breaking changes that need to be handled across your codebase. ### Example: Refactoring a Prisma query after a schema change #### Prompt _Refactor this Prisma query to support soft deletion using a `deletedAt` timestamp field in the User model._ #### Initial code ```ts const users = await prisma.user.findMany(); ``` #### Refactored code ```ts const users = await prisma.user.findMany({ where: { deletedAt: null } }); ``` ## Generating seeding scripts ### How Tabnine helps Seeding a database with realistic test data can be cumbersome. Realistic seed data is helpful during development because it gives the developer a better impression of the application when it's used in the real-world. Tabnine can help with database seeding by: - Generating scripts with structured seed data based on the schema and with specific requirements. - Creating real-looking placeholder data that can be used to test the app. - Generate specific data to cover edge cases. ### Example: Creating a seed script #### Prompt _Generate a Prisma seed script for populating User, Organization, and Subscription models._ #### Generated code ```ts import { PrismaClient } from "@prisma/client"; const prisma = new PrismaClient(); async function main() { await prisma.organization.create({ data: { name: "Prisma Corp", slug: "prisma-corp", subscription: { create: { plan: "PRO", status: "ACTIVE" } }, users: { create: [ { name: "Alice Doe", email: "alice@prisma.io" }, { name: "Bob Smith", email: "bob@prisma.io" } ] } } }); console.log("Seed data created successfully"); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); }); ``` --- # Windsurf URL: https://www.prisma.io/docs/orm/more/ai-tools/windsurf [Windsurf Editor](https://windsurf.com/editor/) is an AI-powered code editor designed to boost productivity by automating repetitive coding tasks. When paired with Prisma, a robust and type-safe toolkit for database workflows, it becomes a powerful solution for managing and optimizing database schemas, queries, and data seeding. This guide provides detailed instructions for effectively using Prisma with Windsurf to: - Define project-specific best practices with `.windsurfrules`. - Use Windsurf's context-aware capabilities. - Generate schemas, queries, and seed data tailored to your database. :::note While this guide is focused on Windsurf, these patterns should work with any AI editor. [Let us know on X](https://pris.ly/x?utm_source=docs&utm_medium=inline_text) if you'd like us to create guides for your preferred tool! ::: ## Prisma MCP server Prisma provides its own [Model Context Protocol (MCP)](https://modelcontextprotocol.io/introduction) server that lets you manage Prisma Postgres databases, model database schemas, and even chat through migrations. Learn more about how you can add it to Windsurf [here](/postgres/mcp-server#windsurf). ## Defining project-specific rules with `.windsurfrules` The [`.windsurfrules` file](https://docs.windsurf.com/windsurf/memories#windsurfrules) in Windsurf allows you to enforce best practices and development standards tailored to your Prisma project. By defining clear and consistent rules, you can ensure that Windsurf generates clean, maintainable, and project-specific code with minimal manual adjustments. To implement these rules, create a `.windsurfrules` file in the root of your project. Below is an example configuration:
Example .windsurfrules file ```text file=.windsurfrules showLineNumbers You are a senior TypeScript/JavaScript programmer with expertise in Prisma, clean code principles, and modern backend development. Generate code, corrections, and refactorings that comply with the following guidelines: TypeScript General Guidelines Basic Principles - Use English for all code and documentation. - Always declare explicit types for variables and functions. - Avoid using "any". - Create precise, descriptive types. - Use JSDoc to document public classes and methods. - Maintain a single export per file. - Write self-documenting, intention-revealing code. Nomenclature - Use PascalCase for classes and interfaces. - Use camelCase for variables, functions, methods. - Use kebab-case for file and directory names. - Use UPPERCASE for environment variables and constants. - Start function names with a verb. - Use verb-based names for boolean variables: - isLoading, hasError, canDelete - Use complete words, avoiding unnecessary abbreviations. - Exceptions: standard abbreviations like API, URL - Accepted short forms: - i, j for loop indices - err for errors - ctx for contexts Functions - Write concise, single-purpose functions. - Aim for less than 20 lines of code. - Name functions descriptively with a verb. - Minimize function complexity: - Use early returns. - Extract complex logic to utility functions. - Leverage functional programming techniques: - Prefer map, filter, reduce. - Use arrow functions for simple operations. - Use named functions for complex logic. - Use object parameters for multiple arguments. - Maintain a single level of abstraction. Data Handling - Encapsulate data in composite types. - Prefer immutability. - Use readonly for unchanging data. - Use as const for literal values. - Validate data at the boundaries. Error Handling - Use specific, descriptive error types. - Provide context in error messages. - Use global error handling where appropriate. - Log errors with sufficient context. Prisma-Specific Guidelines Schema Design - Use meaningful, domain-driven model names. - Leverage Prisma schema features: - Use @id for primary keys. - Use @unique for natural unique identifiers. - Utilize @relation for explicit relationship definitions. - Keep schemas normalized and DRY. - Use meaningful field names and types. - Implement soft delete with deletedAt timestamp. - Use Prisma's native type decorators. Prisma Client Usage - Always use type-safe Prisma client operations. - Prefer transactions for complex, multi-step operations. - Use Prisma middleware for cross-cutting concerns: - Logging - Soft delete - Auditing - Handle optional relations explicitly. - Use Prisma's filtering and pagination capabilities. Database Migrations - Create migrations for schema changes. - Use descriptive migration names. - Review migrations before applying. - Never modify existing migrations. - Keep migrations idempotent. Error Handling with Prisma - Catch and handle Prisma-specific errors: - PrismaClientKnownRequestError - PrismaClientUnknownRequestError - PrismaClientValidationError - Provide user-friendly error messages. - Log detailed error information for debugging. Testing Prisma Code - Use in-memory database for unit tests. - Mock Prisma client for isolated testing. - Test different scenarios: - Successful operations - Error cases - Edge conditions - Use factory methods for test data generation. - Implement integration tests with actual database. Performance Considerations - Use select and include judiciously. - Avoid N+1 query problems. - Use findMany with take and skip for pagination. - Leverage Prisma's distinct for unique results. - Profile and optimize database queries. Security Best Practices - Never expose raw Prisma client in APIs. - Use input validation before database operations. - Implement row-level security. - Sanitize and validate all user inputs. - Use Prisma's built-in protections against SQL injection. Coding Style - Keep Prisma-related code in dedicated repositories/modules. - Separate data access logic from business logic. - Create repository patterns for complex queries. - Use dependency injection for Prisma services. Code Quality - Follow SOLID principles. - Prefer composition over inheritance. - Write clean, readable, and maintainable code. - Continuously refactor and improve code structure. Development Workflow - Use version control (Git). - Implement comprehensive test coverage. - Use continuous integration. - Perform regular code reviews. - Keep dependencies up to date. ```
This file ensures consistent and maintainable code generation, reducing manual intervention while improving project quality. ## Using Windsurf's context-aware capabilities Windsurf's [context-awareness](https://docs.windsurf.com/context-awareness/overview) features let you leverage both your project files and external resources to enhance the AI's understanding of your project. By including your Prisma schema and relevant documentation in the context, you enable Windsurf to generate more accurate queries, tests, and seed data based on your database schema. ### Including Additional Prisma Resources Windsurf comes with built-in knowledge of common libraries, but you can further enhance its awareness by explicitly referencing external Prisma resources. This is especially useful for staying up-to-date or providing authoritative context for code generation and best practices. For example, you might reference: - [Prisma Changelog](https://www.prisma.io/changelog) - [Prisma Blog](https://www.prisma.io/blog) - [Prisma Documentation](/) #### Reference the resource in your requests: When asking for code, explanations, or reviews, include the link to the relevant Prisma resource and specify that it should be used as a reference. ```terminal Generate a migration script using best practices from prisma.io/docs. ``` #### Request persistent awareness: Ask Windsurf to always consider a specific resource for all Prisma-related work in your project. ```terminal Always use the Prisma Changelog at prisma.io/changelog for Prisma updates in this project. ``` #### Ask for regular updates: If you want Windsurf to check for updates or new features, explicitly request it. ```terminal Before suggesting Prisma code, check the latest changes from prisma.io/changelog. ``` By referencing external resources directly in your requests or project guidelines, you ensure Windsurf leverages the most current and relevant Prisma information. ### Using schema as context Out of the box, Windsurf automatically considers the current file, other open files, and indexed portions of your codebase as context. To ensure Cascade fully leverages your Prisma schema, keep your `schema.prisma` file open or pinned in the editor. ## Generating Prisma schema Windsurf can generate Prisma schemas from high-level descriptions, enabling you to quickly establish a solid foundation for your database schema. By providing a clear and detailed prompt, Windsurf creates Prisma schemas tailored to your requirements. Whether you need a general foundational schema or a highly specific one for detailed use cases, Windsurf can deliver with precision. Here's an example prompt and its corresponding result: :::note LLMs may produce different results each time, even with the same prompt. ::: ```text copy "Create a Prisma schema for a SaaS app using PostgreSQL as a provider with `User`, `Organization`, and `Subscription` models, ensuring all models include `createdAt` and `updatedAt` DateTime fields with defaults, a soft-delete `deletedAt` field, and proper relationships between entities." ``` ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) email String @unique name String password String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime? organization Organization @relation(fields: [organizationId], references: [id]) organizationId Int role UserRole @default(MEMBER) } model Organization { id Int @id @default(autoincrement()) name String slug String @unique subscription Subscription? users User[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime? } model Subscription { id Int @id @default(autoincrement()) organization Organization @relation(fields: [organizationId], references: [id]) organizationId Int @unique plan SubscriptionPlan status SubscriptionStatus @default(ACTIVE) startDate DateTime endDate DateTime? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt deletedAt DateTime? } enum UserRole { ADMIN MEMBER } enum SubscriptionPlan { FREE BASIC PREMIUM ENTERPRISE } enum SubscriptionStatus { ACTIVE CANCELED EXPIRED PAST_DUE } ``` ## Generating Prisma queries Windsurf can help you create queries tailored to your Prisma schema, whether for basic data retrieval or complex, optimized operations. To get the best results, focus on writing clear, specific prompts that define your requirements, such as the fields to include, conditions to apply, and relationships to traverse. This ensures Windsurf generates accurate, performant, and type-safe queries. Here's an example prompt and its resulting query: ```text copy "Generate a query to retrieve all User records associated with an Organization that has an `active` Subscription, while excluding any records where the `deletedAt` field is set." ``` ```ts showLineNumbers const activeUsers = await prisma.user.findMany({ where: { deletedAt: null, organization: { deletedAt: null, subscription: { deletedAt: null, status: 'ACTIVE' } } }, include: { organization: { include: { subscription: true } } }, orderBy: { createdAt: 'desc' }, skip: 0, take: 10 }); ``` ## Creating seed files with Windsurf Writing seed scripts can be a tedious process, but Windsurf simplifies it by quickly generating structured and organized seed code. By providing clear instructions, you can guide Windsurf to create scripts that populate your database with realistic data, including handling relationships and complex structures defined in your schema. Here's an example prompt and its resulting seed script: ```text copy "Generate code to populate the Prisma schema with realistic data for the User, Organization, and Subscription models, ensuring all necessary fields are included." ``` ```ts file=seed.ts import { PrismaClient, UserRole, SubscriptionPlan, SubscriptionStatus, } from "@prisma/client"; const prisma = new PrismaClient(); async function main() { // Clear existing data await prisma.user.deleteMany(); await prisma.subscription.deleteMany(); await prisma.organization.deleteMany(); const organizations = [ { name: "Tech Innovators", slug: "tech-innovators", subscription: { plan: SubscriptionPlan.ENTERPRISE, status: SubscriptionStatus.ACTIVE, startDate: new Date("2024-01-01"), }, users: [ { name: "Emma Thompson", email: "emma@techinnovators.com", role: UserRole.ADMIN, password: "password123", }, { name: "Michael Chen", email: "michael@techinnovators.com", role: UserRole.MEMBER, password: "password123", }, ], }, { name: "Digital Solutions", slug: "digital-solutions", subscription: { plan: SubscriptionPlan.PREMIUM, status: SubscriptionStatus.ACTIVE, startDate: new Date("2024-01-15"), }, users: [ { name: "Sarah Wilson", email: "sarah@digitalsolutions.com", role: UserRole.ADMIN, password: "password123", }, { name: "James Miller", email: "james@digitalsolutions.com", role: UserRole.MEMBER, password: "password123", }, ], }, { name: "Cloud Systems", slug: "cloud-systems", subscription: { plan: SubscriptionPlan.BASIC, status: SubscriptionStatus.ACTIVE, startDate: new Date("2024-02-01"), }, users: [ { name: "David Garcia", email: "david@cloudsystems.com", role: UserRole.ADMIN, password: "password123", }, { name: "Lisa Wang", email: "lisa@cloudsystems.com", role: UserRole.MEMBER, password: "password123", }, ], }, { name: "Data Analytics Co", slug: "data-analytics", subscription: { plan: SubscriptionPlan.PREMIUM, status: SubscriptionStatus.ACTIVE, startDate: new Date("2024-01-10"), }, users: [ { name: "Alex Johnson", email: "alex@dataanalytics.com", role: UserRole.ADMIN, password: "password123", }, { name: "Rachel Kim", email: "rachel@dataanalytics.com", role: UserRole.MEMBER, password: "password123", }, ], }, { name: "Smart Solutions", slug: "smart-solutions", subscription: { plan: SubscriptionPlan.FREE, status: SubscriptionStatus.ACTIVE, startDate: new Date("2024-02-15"), }, users: [ { name: "Daniel Brown", email: "daniel@smartsolutions.com", role: UserRole.ADMIN, password: "password123", }, { name: "Maria Rodriguez", email: "maria@smartsolutions.com", role: UserRole.MEMBER, password: "password123", }, ], }, ]; for (const org of organizations) { const createdOrg = await prisma.organization.create({ data: { name: org.name, slug: org.slug, subscription: { create: { plan: org.subscription.plan, status: org.subscription.status, startDate: org.subscription.startDate, }, }, }, }); for (const user of org.users) { await prisma.user.create({ data: { name: user.name, email: user.email, password: user.password, role: user.role, organizationId: createdOrg.id, }, }); } } console.log("Seed data created successfully"); } main() .catch((e) => { console.error(e); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); }); ``` ## Additional resources Using Windsurf with Prisma can speed up development while ensuring clean and maintainable database code. To keep learning: - [Windsurf Documentation](https://docs.windsurf.com/windsurf/getting-started) - [Prisma Documentation](/) --- # AI tools URL: https://www.prisma.io/docs/orm/more/ai-tools/index ## In this section Scaffold a new Prisma project with a new database using the `prisma init --prompt` command: ```terminal npx prisma init --prompt "Simple habit tracker application" ``` This will generate a Prisma schema based on the prompt and deploy it to a fresh [Prisma Postgres](/postgres) instance. ## Prisma MCP server Prisma provides its own [Model Context Protocol](https://modelcontextprotocol.io/introduction) (MCP) server that lets you manage Prisma Postgres databases, model database schemas and chat through migrations. Learn more about it [here](/postgres/mcp-server). --- # TypeORM URL: https://www.prisma.io/docs/orm/more/comparisons/prisma-and-typeorm This page compares Prisma ORM and [TypeORM](https://typeorm.io/). If you want to learn how to migrate from TypeORM to Prisma ORM, check out this [guide](/guides/migrate-from-typeorm). ## TypeORM vs Prisma ORM While Prisma ORM and TypeORM solve similar problems, they work in very different ways. **TypeORM** is a traditional ORM which maps _tables_ to _model classes_. These model classes can be used to generate SQL migrations. Instances of the model classes then provide an interface for CRUD queries to an application at runtime. **Prisma ORM** is a new kind of ORM that mitigates many problems of traditional ORMs, such as bloated model instances, mixing business with storage logic, lack of type-safety or unpredictable queries caused e.g. by lazy loading. It uses the [Prisma schema](/orm/prisma-schema) to define application models in a declarative way. Prisma Migrate then allows to generate SQL migrations from the Prisma schema and executes them against the database. CRUD queries are provided by Prisma Client, a lightweight and entirely type-safe database client for Node.js and TypeScript. ## API design & Level of abstraction TypeORM and Prisma ORM operate on different levels of abstraction. TypeORM is closer to mirroring SQL in its API while Prisma Client provides a higher-level abstraction that was carefully designed with the common tasks of application developers in mind. Prisma ORM's API design heavily leans on the idea of [making the right thing easy](https://jason.energy/right-thing-easy-thing/). While Prisma Client operates at a higher level of abstraction, it strives to expose the full power of the underlying database, allowing you to drop down to [raw SQL](/orm/prisma-client/using-raw-sql/raw-queries) at any time if your use case requires it. The following sections examine a few examples for how Prisma ORM's and TypeORM's APIs differ in certain scenarios and what the rationale of Prisma ORM's API design is in these cases. ### Filtering TypeORM primarily leans on SQL operators for filtering lists or records, e.g. with the `find` method. Prisma ORM on the other hand, provides a more [generic set of operators](/orm/prisma-client/queries/filtering-and-sorting#filter-conditions-and-operators) that are intuitive to use. It should also be noted that, as explained in the type-safety section [below](#filtering-1), TypeORM loses type-safety in filter queries in many scenarios. A good example of how the filtering APIs of both TypeORM and Prisma ORM differ is by looking at `string` filters. While TypeORM primarily provides the filter based on the `ILike` operator which comes directly from SQL, Prisma ORM provides more specific operators that developers can use, e.g.: `contains`, `startsWith` and `endsWith`. ```ts const posts = await prisma.post.findMany({ where: { title: 'Hello World', }, }) ``` ```ts const posts = await postRepository.find({ where: { title: ILike('Hello World'), }, }) ``` ```ts const posts = await prisma.post.findMany({ where: { title: { contains: 'Hello World' }, }, }) ``` ```ts const posts = await postRepository.find({ where: { title: ILike('%Hello World%'), }, }) ``` ```ts const posts = await prisma.post.findMany({ where: { title: { startsWith: 'Hello World' }, }, }) ``` ```ts const posts = await postRepository.find({ where: { title: ILike('Hello World%'), }, }) ``` ```ts const posts = await prisma.post.findMany({ where: { title: { endsWith: 'Hello World' }, }, }) ``` ```ts const posts = await postRepository.find({ where: { title: ILike('%Hello World'), }, }) ``` ### Pagination TypeORM only offers limit-offset pagination while Prisma ORM conveniently provides dedicated APIs for both limit-offset but also cursor-based. You can learn more about both approaches in the [Pagination](/orm/prisma-client/queries/pagination) section of the docs or in the API comparison [below](#pagination-1). ### Relations Working with records that are connected via foreign keys can become very complex in SQL. Prisma ORM's concept of [virtual relation field](/orm/prisma-schema/data-model/relations#relation-fields) enables an intuitive and convenient way for application developers to work with related data. Some benefits of Prisma ORM's approach are: - traversing relationships via the fluent API ([docs](/orm/prisma-client/queries/relation-queries#fluent-api)) - nested writes that enable updating/creating connected records ([docs](/orm/prisma-client/queries/relation-queries#nested-writes)) - applying filters on related records ([docs](/orm/prisma-client/queries/relation-queries#relation-filters)) - easy and type-safe querying of nested data without worrying about JOINs ([docs](/orm/prisma-client/queries/relation-queries#nested-reads)) - creating nested TypeScript typings based on models and their relations ([docs](/orm/prisma-client/type-safety)) - intuitive modeling of relations in the data model via relation fields ([docs](/orm/prisma-schema/data-model/relations)) - implicit handling of relation tables (also sometimes called JOIN, link, pivot or junction tables) ([docs](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations)) ### Data modeling and migrations Prisma models are defined in the [Prisma schema](/orm/prisma-schema) while TypeORM uses classes and experimental TypeScript decorators for model definitions. With the Active Record ORM pattern, TypeORM's approach often leads to complex model instances that are becoming hard to maintain as an application grows. Prisma ORM on the other hand generates a lightweight database client that exposes a tailored and fully type-safe API to read and write data for the models that are defined in the Prisma schema, following the DataMapper ORM pattern rather than Active Record. Prisma ORM's DSL for data modeling is lean, simple and intuitive to use. When modeling data in VS Code, you can further take advantage of Prisma ORM's powerful VS Code extension with features like autocompletion, quick fixes, jump to definition and other benefits that increase developer productivity. ```prisma model User { id Int @id @default(autoincrement()) name String? email String @unique posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) authorId Int? author User? @relation(fields: [authorId], references: [id]) } ``` ```ts import { Entity, PrimaryGeneratedColumn, Column, OneToMany, ManyToOne, } from 'typeorm' @Entity() export class User { @PrimaryGeneratedColumn() id: number @Column({ nullable: true }) name: string @Column({ unique: true }) email: string @OneToMany((type) => Post, (post) => post.author) posts: Post[] } @Entity() export class Post { @PrimaryGeneratedColumn() id: number @Column() title: string @Column({ nullable: true }) content: string @Column({ default: false }) published: boolean @ManyToOne((type) => User, (user) => user.posts) author: User } ``` Migrations work in similar fashions in TypeORM and Prisma ORM. Both tools follow the approach of generating SQL files based on the provided model definitions and provide a CLI to execute them against the database. The SQL files can be modified before the migrations are executed so that any custom database operation can be performed with either migration system. ## Type safety TypeORM has been one of the first ORMs in the Node.js ecosystem to fully embrace TypeScript and has done a great job in enabling developers to get a certain level of type safety for their database queries. However, there are numerous situations where the type safety guarantees of TypeORM fall short. The following sections describe the scenarios where Prisma ORM can provide stronger guarantees for the types of query results. ### Selecting fields This section explains the differences in type safety when selecting a subset of a model's fields in a query. #### TypeORM TypeORM provides a `select` option for its [`find`](https://typeorm.io/find-options) methods (e.g. `find`, `findByIds`, `findOne`, ...), for example: ```ts const postRepository = getManager().getRepository(Post) const publishedPosts: Post[] = await postRepository.find({ where: { published: true }, select: ['id', 'title'], }) ``` ```ts @Entity() export class Post { @PrimaryGeneratedColumn() id: number @Column() title: string @Column({ nullable: true }) content: string @Column({ default: false }) published: boolean @ManyToOne((type) => User, (user) => user.posts) author: User } ``` While each object in the returned `publishedPosts` array only carries the selected `id` and `title` properties at runtime, the TypeScript compiler doesn't have any knowledge of this. It will allow you to access any other properties defined on the `Post` entity after the query, for example: ```ts const post = publishedPosts[0] // The TypeScript compiler has no issue with this if (post.content.length > 0) { console.log(`This post has some content.`) } ``` This code will result in an error at runtime: ``` TypeError: Cannot read property 'length' of undefined ``` The TypeScript compiler only sees the `Post` type of the returned objects, but it doesn't know about the fields that these objects _actually_ carry at runtime. It therefore can't protect you from accessing fields that have not been retrieved in the database query, resulting in a runtime error. #### Prisma ORM Prisma Client can guarantee full type safety in the same situation and protects you from accessing fields that were not retrieved from the database. Consider the same example with a Prisma Client query: ```ts const publishedPosts = await prisma.post.findMany({ where: { published: true }, select: { id: true, title: true, }, }) const post = publishedPosts[0] // The TypeScript compiler will not allow this if (post.content.length > 0) { console.log(`This post has some content.`) } ``` ```prisma model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) authorId Int? author User? @relation(fields: [authorId], references: [id]) } ``` In this case, the TypeScript compiler will throw the following error already at compile-time: ``` [ERROR] 14:03:39 ⨯ Unable to compile TypeScript: src/index.ts:36:12 - error TS2339: Property 'content' does not exist on type '{ id: number; title: string; }'. 42 if (post.content.length > 0) { ``` This is because Prisma Client generates the return type for its queries _on the fly_. In this case, `publishedPosts` is typed as follows: ```ts const publishedPosts: { id: number title: string }[] ``` It therefore is impossible for you to accidentally access a property on a model that has not been retrieved in a query. ### Loading relations This section explains the differences in type safety when loading relations of a model in a query. In traditional ORMs, this is sometimes called _eager loading_. #### TypeORM TypeORM allows to eagerly load relations from the database via the `relations` option that can be passed to its [`find`](https://typeorm.io/find-options) methods. Consider this example: ```ts const postRepository = getManager().getRepository(Post) const publishedPosts: Post[] = await postRepository.find({ where: { published: true }, relations: ['author'], }) ``` ```ts @Entity() export class Post { @PrimaryGeneratedColumn() id: number @Column() title: string @Column({ nullable: true }) content: string @Column({ default: false }) published: boolean @ManyToOne((type) => User, (user) => user.posts) author: User } ``` ```ts @Entity() export class User { @PrimaryGeneratedColumn() id: number @Column({ nullable: true }) name: string @Column({ unique: true }) email: string @OneToMany((type) => Post, (post) => post.author) posts: Post[] } ``` Unlike with `select`, TypeORM does _not_ provide autocompletion, nor any type-safety for the strings that are passed to the `relations` option. This means, the TypeScript compiler is not able to catch any typos that are made when querying these relations. For example, it would allow for the following query: ```ts const publishedPosts: Post[] = await postRepository.find({ where: { published: true }, // this query would lead to a runtime error because of a typo relations: ['authors'], }) ``` This subtle typo would now lead to the following runtime error: ``` UnhandledPromiseRejectionWarning: Error: Relation "authors" was not found; please check if it is correct and really exists in your entity. ``` #### Prisma ORM Prisma ORM protects you from mistakes like this and thus eliminates a whole class of errors that can occur in your application at runtime. When using `include` to load a relation in a Prisma Client query, you can not only take advantage of autocompletion to specify the query, but the result of the query will also be properly typed: ```ts const publishedPosts = await prisma.post.findMany({ where: { published: true }, include: { author: true }, }) ``` ```ts model User { id Int @id @default(autoincrement()) name String? email String @unique posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) authorId Int? author User? @relation(fields: [authorId], references: [id]) } ``` Again, the type of `publishedPosts` is generated on the fly and looks as follows: ```ts const publishedPosts: (Post & { author: User })[] ``` For reference, this is what the `User` and `Post` types look like that Prisma Client generates for your Prisma models: ```ts // Generated by Prisma ORM export type User = { id: number name: string | null email: string } ``` ```ts // Generated by Prisma ORM export type Post = { id: number title: string content: string | null published: boolean authorId: number | null } ``` ### Filtering This section explains the differences in type safety when filtering a list of records using `where`. #### TypeORM TypeORM allows to pass a `where` option to its [`find`](https://typeorm.io/find-options) methods to filter the list of returned records according to specific criteria. These criteria can be defined with respect to a model's properties. ##### Loosing type-safety using operators Consider this example: ```ts const postRepository = getManager().getRepository(Post) const publishedPosts: Post[] = await postRepository.find({ where: { published: true, title: ILike('Hello World'), views: MoreThan(0), }, }) ``` ```ts @Entity() export class Post { @PrimaryGeneratedColumn() id: number @Column() title: string @Column({ nullable: true }) content: string @Column({ nullable: true }) views: number @Column({ default: false }) published: boolean @ManyToOne((type) => User, (user) => user.posts) author: User } ``` This code runs properly and produces a valid query at runtime. However, the `where` option is not really type-safe in various different scenarios. When using a `FindOperator` like `ILike` or `MoreThan` that only work for specific types (`ILike` works for strings, `MoreThan` for numbers), you're losing the guarantee of providing the correct type for the model's field. For example, you can provide a string to the `MoreThan` operator. The TypeScript compiler will not complain and your application will only fail at runtime: ```ts const postRepository = getManager().getRepository(Post) const publishedPosts: Post[] = await postRepository.find({ where: { published: true, title: ILike('Hello World'), views: MoreThan('test'), }, }) ``` The code above results in a runtime error that the TypeScript compiler doesn't catch for you: ``` error: error: invalid input syntax for type integer: "test" ``` ##### Specifying non-existing properties Also note that the TypeScript compiler allows you to specify properties on the `where` option that don't exist on your models – again resulting in runtime errors: ```ts const publishedPosts: Post[] = await postRepository.find({ where: { published: true, title: ILike('Hello World'), viewCount: 1, }, }) ``` In this case, your application again fails at runtime with the following error: ``` EntityColumnNotFound: No entity column "viewCount" was found. ``` #### Prisma ORM Both filtering scenarios that are problematic with TypeORM in terms of type-safety are covered by Prisma ORM in a fully type-safe way. ##### Type-safe usage of operators With Prisma ORM, the TypeScript compiler enforces the correct usage of an operator per field: ```ts const publishedPosts = await prisma.post.findMany({ where: { published: true, title: { contains: 'Hello World' }, views: { gt: 0 }, }, }) ``` It would not be allowed to specify the same problematic query shown above with Prisma Client: ```ts const publishedPosts = await prisma.post.findMany({ where: { published: true, title: { contains: 'Hello World' }, views: { gt: 'test' }, // Caught by the TypeScript compiler }, }) ``` The TypeScript compiler would catch this and throw the following error to protect you from a runtime failure of the app: ``` [ERROR] 16:13:50 ⨯ Unable to compile TypeScript: src/index.ts:39:5 - error TS2322: Type '{ gt: string; }' is not assignable to type 'number | IntNullableFilter'. Type '{ gt: string; }' is not assignable to type 'IntNullableFilter'. Types of property 'gt' are incompatible. Type 'string' is not assignable to type 'number'. 42 views: { gt: "test" } ``` ##### Type-safe definition of filters as model properties With TypeORM, you are able to specify a property on the `where` option that doesn't map to a model's field. In the above example, filtering for `viewCount` therefore led to a runtime error because the field actually is called `views`. With Prisma ORM, the TypeScript compiler will not allow to reference any properties inside of `where` that don't exist on the model: ```ts const publishedPosts = await prisma.post.findMany({ where: { published: true, title: { contains: 'Hello World' }, viewCount: { gt: 0 }, // Caught by the TypeScript compiler }, }) ``` Again, the TypeScript compiler complains with the following message to protect you from your own mistakes: ```ts [ERROR] 16:16:16 ⨯ Unable to compile TypeScript: src/index.ts:39:5 - error TS2322: Type '{ published: boolean; title: { contains: string; }; viewCount: { gt: number; }; }' is not assignable to type 'PostWhereInput'. Object literal may only specify known properties, and 'viewCount' does not exist in type 'PostWhereInput'. 42 viewCount: { gt: 0 } ``` ### Creating new records This section explains the differences in type safety when creating new records. #### TypeORM With TypeORM, there are two main ways to create new records in the database: `insert` and `save`. Both methods allow developers to submit data that can lead to runtime errors when _required_ fields are not provided. Consider this example: ```ts const userRepository = getManager().getRepository(User) const newUser = new User() newUser.name = 'Alice' userRepository.save(newUser) ``` ```ts const userRepository = getManager().getRepository(User) userRepository.insert({ name: 'Alice', }) ``` ```ts @Entity() export class User { @PrimaryGeneratedColumn() id: number @Column({ nullable: true }) name: string @Column({ unique: true }) email: string @OneToMany((type) => Post, (post) => post.author) posts: Post[] } ``` No matter if you're using `save` or `insert` for record creation with TypeORM, you will get the following runtime error if you forget to provide the value for a required field: ``` QueryFailedError: null value in column "email" of relation "user" violates not-null constraint ``` The `email` field is defined as required on the `User` entity (which is enforced by a `NOT NULL` constraint in the database). ### Prisma ORM Prisma ORM protects you from these kind of mistakes by enforcing that you submit values for _all_ required fields of a model. For example, the following attempt to create a new `User` where the required `email` field is missing would be caught by the TypeScript compiler: ```ts const newUser = await prisma.user.create({ data: { name: 'Alice', }, }) ``` ```prisma model User { id Int @id @default(autoincrement()) name String? email String @unique } ``` It would lead to the following compile-time error: ``` [ERROR] 10:39:07 ⨯ Unable to compile TypeScript: src/index.ts:39:5 - error TS2741: Property 'email' is missing in type '{ name: string; }' but required in type 'UserCreateInput'. ``` ## API comparison ### Fetching single objects **Prisma ORM** ```ts const user = await prisma.user.findUnique({ where: { id: 1, }, }) ``` **TypeORM** ```ts const userRepository = getRepository(User) const user = await userRepository.findOne(id) ``` ### Fetching selected scalars of single objects **Prisma ORM** ```ts const user = await prisma.user.findUnique({ where: { id: 1, }, select: { name: true, }, }) ``` **TypeORM** ```ts const userRepository = getRepository(User) const user = await userRepository.findOne(id, { select: ['id', 'email'], }) ``` ### Fetching relations **Prisma ORM** ```ts const posts = await prisma.user.findUnique({ where: { id: 2, }, include: { post: true, }, }) ``` ```ts const posts = await prisma.user .findUnique({ where: { id: 2, }, }) .post() ``` > **Note**: `select` return a `user` object that includes a `post` array, whereas the fluent API only returns a `post` array. **TypeORM** ```ts const userRepository = getRepository(User) const user = await userRepository.findOne(id, { relations: ['posts'], }) ``` ```ts const userRepository = getRepository(User) const user = await userRepository.findOne(id, { join: { alias: 'user', leftJoinAndSelect: { posts: 'user.posts', }, }, }) ``` ```ts const userRepository = getRepository(User) const user = await userRepository.findOne(id) ``` ### Filtering for concrete values **Prisma ORM** ```ts const posts = await prisma.post.findMany({ where: { title: { contains: 'Hello', }, }, }) ``` **TypeORM** ```ts const userRepository = getRepository(User) const users = await userRepository.find({ where: { name: 'Alice', }, }) ``` ### Other filter criteria **Prisma ORM** Prisma ORM generates many [additional filters](/orm/prisma-client/queries/filtering-and-sorting) that are commonly used in modern application development. **TypeORM** TypeORM provides [built-in operators](https://typeorm.io/find-options#advanced-options) that can be used to create more complex comparisons ### Relation filters **Prisma ORM** Prisma ORM lets you filter a list based on a criteria that applies not only to the models of the list being retrieved, but to a _relation_ of that model. For example, the following query returns users with one or more posts with "Hello" in the title: ```ts const posts = await prisma.user.findMany({ where: { Post: { some: { title: { contains: 'Hello', }, }, }, }, }) ``` **TypeORM** TypeORM doesn't offer a dedicated API for relation filters. You can get similar functionality by using the `QueryBuilder` or writing the queries by hand. ### Pagination **Prisma ORM** Cursor-style pagination: ```ts const page = await prisma.post.findMany({ before: { id: 242, }, last: 20, }) ``` Offset pagination: ```ts const cc = await prisma.post.findMany({ skip: 200, first: 20, }) ``` **TypeORM** ```ts const postRepository = getRepository(Post) const posts = await postRepository.find({ skip: 5, take: 10, }) ``` ### Creating objects **Prisma ORM** ```ts const user = await prisma.user.create({ data: { email: 'alice@prisma.io', }, }) ``` **TypeORM** ```ts const user = new User() user.name = 'Alice' user.email = 'alice@prisma.io' await user.save() ``` ```ts const userRepository = getRepository(User) const user = await userRepository.create({ name: 'Alice', email: 'alice@prisma.io', }) await user.save() ``` ```ts const userRepository = getRepository(User) await userRepository.insert({ name: 'Alice', email: 'alice@prisma.io', }) ``` ### Updating objects **Prisma ORM** ```ts const user = await prisma.user.update({ data: { name: 'Alicia', }, where: { id: 2, }, }) ``` **TypeORM** ```ts const userRepository = getRepository(User) const updatedUser = await userRepository.update(id, { name: 'James', email: 'james@prisma.io', }) ``` ### Deleting objects **Prisma ORM** ```ts const deletedUser = await prisma.user.delete({ where: { id: 10, }, }) ``` **TypeORM** ```ts const userRepository = getRepository(User) await userRepository.delete(id) ``` ```ts const userRepository = getRepository(User) const deletedUser = await userRepository.remove(user) ``` ### Batch updates **Prisma ORM** ```ts const user = await prisma.user.updateMany({ data: { name: 'Published author!', }, where: { Post: { some: { published: true, }, }, }, }) ``` **TypeORM** You can use the [query builder to update entities in your database](https://typeorm.io/update-query-builder). ### Batch deletes **Prisma ORM** ```ts const users = await prisma.user.deleteMany({ where: { id: { in: [1, 2, 6, 6, 22, 21, 25], }, }, }) ``` **TypeORM** ```ts const userRepository = getRepository(User) await userRepository.delete([id1, id2, id3]) ``` ```ts const userRepository = getRepository(User) const deleteUsers = await userRepository.remove([user1, user2, user3]) ``` ### Transactions **Prisma ORM** ```ts const user = await prisma.user.create({ data: { email: 'bob.rufus@prisma.io', name: 'Bob Rufus', Post: { create: [ { title: 'Working at Prisma' }, { title: 'All about databases' }, ], }, }, }) ``` **TypeORM** ```ts await getConnection().$transaction(async (transactionalEntityManager) => { const user = getRepository(User).create({ name: 'Bob', email: 'bob@prisma.io', }) const post1 = getRepository(Post).create({ title: 'Join us for GraphQL Conf in 2019', }) const post2 = getRepository(Post).create({ title: 'Subscribe to GraphQL Weekly for GraphQL news', }) user.posts = [post1, post2] await transactionalEntityManager.save(post1) await transactionalEntityManager.save(post2) await transactionalEntityManager.save(user) }) ``` --- # Sequelize URL: https://www.prisma.io/docs/orm/more/comparisons/prisma-and-sequelize This page compares the Prisma ORM and [Sequelize](https://sequelize.org/docs/v6/) APIs. ## Sequelize vs Prisma ORM While Prisma ORM and Sequelize solve similar problems, they work in very different ways. **Sequelize** is a traditional ORM which maps _tables_ to _model classes_. Instances of the model classes then provide an interface for CRUD queries to an application at runtime. **Prisma ORM** is a new kind of ORM that mitigates many problems of traditional ORMs, such as bloated model instances, mixing business with storage logic, lack of type-safety or unpredictable queries caused e.g. by lazy loading. It uses the [Prisma schema](/orm/prisma-schema) to define application models in a declarative way. Prisma Migrate then allows to generate SQL migrations from the Prisma schema and executes them against the database. CRUD queries are provided by Prisma Client, a lightweight and entirely type-safe database client for Node.js and TypeScript. ## API comparison ### Fetching single objects **Prisma ORM** ```ts const user = await prisma.user.findUnique({ where: { id: 1, }, }) ``` **Sequelize** ```ts const user = await User.findByPk(id) ``` ### Fetching selected scalars of single objects **Prisma ORM** ```ts const user = await prisma.user.findUnique({ where: { id: 1, }, select: { name: true, }, }) ``` **Sequelize** ```ts const user = await User.findByPk(1, { attributes: ['name'], raw: true }) ``` :::tip Use the `raw: true` query option to return plain JavaScript objects. ::: ### Fetching relations **Prisma ORM** ```ts const posts = await prisma.user.findUnique({ where: { id: 2, }, include: { post: true, }, }) ``` ```ts const posts = await prisma.user .findUnique({ where: { id: 2, }, }) .post() ``` > **Note**: `select` returns a `user` object that includes a `post` array, whereas the fluent API only returns a `post` array. **Sequelize** ```ts const user = await User.findByPk(id, { include: [ { model: Post, }, ], }) ``` :::tip Use `model: Post as "Post"` if you used an alias to define the relationship between `User` and `Post` - for example: `User.hasMany(Post, { as: "Post", foreignKey: "authorId" });` ::: ### Filtering for concrete values **Prisma ORM** ```ts const posts = await prisma.post.findMany({ where: { title: { contains: 'Hello', }, }, }) ``` **Sequelize** ```ts const post = await Post.findAll({ raw: true, where: { title: { [Op.like]: '%Hello%', }, }, }) ``` ### Other filter criteria **Prisma ORM** Prisma ORM generates many [additional filters](/orm/prisma-client/queries/filtering-and-sorting) that are commonly used in modern application development. **Sequelize** Sequelize has an [extensive set of operators](https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#operators). ### Relation filters **Prisma ORM** Prisma ORM lets you filter a list based on a criteria that applies not only to the models of the list being retrieved, but to a _relation_ of that model. For example, the following query returns users with one or more posts with "Hello" in the title: ```ts const posts = await prisma.user.findMany({ where: { Post: { some: { title: { contains: 'Hello', }, }, }, }, }) ``` **Sequelize** Sequelize [doesn't offer a dedicated API for relation filters](https://github.com/sequelize/sequelize/issues/10943). You can get similar functionality by sending a raw SQL query to the database. ### Pagination **Prisma ORM** Cursor-style pagination: ```ts const page = await prisma.post.findMany({ before: { id: 242, }, last: 20, }) ``` Offset pagination: ```ts const cc = await prisma.post.findMany({ skip: 200, first: 20, }) ``` **Sequelize** Cursor pagination: ```ts const posts = await Post.findAll({ limit: 20, where: { id: { [Op.gt]: 242, }, }, }) ``` > **Note**: Sequelize use the [Sequelize operators](https://sequelize.org/docs/v6/core-concepts/model-querying-basics/#operators) to perform cursor pagination. Offset pagination: ```ts const posts = await Post.findAll({ offset: 5, limit: 10, }) ``` ### Creating objects **Prisma ORM** ```ts const user = await prisma.user.create({ data: { email: 'alice@prisma.io', }, }) ``` **Sequelize** ```ts const user = User.build({ name: 'Alice', email: 'alice@prisma,io', }) await user.save() ``` ```ts const user = await User.create({ name: 'Alice', email: 'alice@prisma,io', }) ``` ### Updating objects **Prisma ORM** ```ts const user = await prisma.user.update({ data: { name: 'Alicia', }, where: { id: 2, }, }) ``` **Sequelize** ```ts user.name = 'James' user.email = ' alice@prisma.com' await user.save() ``` ```ts await User.update({ name: 'James', email: 'james@prisma.io', }) ``` ### Deleting objects **Prisma ORM** ```ts const user = await prisma.user.delete({ where: { id: 10, }, }) ``` **Sequelize** ```ts await user.destroy() ``` ### Batch updates **Prisma ORM** ```ts const user = await prisma.user.updateMany({ data: { name: 'Published author!', }, where: { email: { contains: 'prisma.io', }, }, }) ``` **Sequelize** ```ts const updatedUsers = await User.update({ { role: "Admin" }, where: { email: { [Op.like]: "%@prisma.io" } }, }) ``` ### Batch deletes **Prisma ORM** ```ts const users = await prisma.user.deleteMany({ where: { id: { in: [1, 2, 6, 6, 22, 21, 25], }, }, }) ``` **Sequelize** ```ts await User.destroy({ where: { id: { [Op.in]: [id1, id2, id3], }, }, }) ``` ### Transactions **Prisma ORM** ```ts const user = await prisma.user.create({ data: { email: 'bob.rufus@prisma.io', name: 'Bob Rufus', Post: { create: [ { title: 'Working at Prisma' }, { title: 'All about databases' }, ], }, }, }) ``` **Sequelize** ```ts return sequelize.$transaction(async (t) => { const user = await User.create( { name: 'Alice', email: 'alice@prisma,io', }, { transaction: t, } ) const post1 = await Post.create( { title: 'Join us for GraphQL Conf in 2019', }, { transaction: t, } ) const post2 = await Post.create( { title: 'Subscribe to GraphQL Weekly for GraphQL news', }, { transaction: t, } ) await user.setPosts([post1, post2]) }) ``` ```ts return sequelize.$transaction(async (transaction) => { try { const user = await User.create({ name: 'Alice', email: 'alice@prisma,io', }) const post1 = await Post.create({ title: 'Join us for GraphQL Conf in 2019', }) const post2 = await Post.create({ title: 'Subscribe to GraphQL Weekly for GraphQL news', }) await user.setPosts([post1, post2]) } catch (e) { return transaction.rollback() } }) ``` --- # Mongoose URL: https://www.prisma.io/docs/orm/more/comparisons/prisma-and-mongoose This page compares the Prisma ORM and [Mongoose](https://mongoosejs.com/docs/guide.html) APIs. If you want to learn how to migrate from Mongoose to Prisma, check out this [guide](/guides/migrate-from-mongoose). ## Fetching single objects **Prisma ORM** ```ts const user = await prisma.user.findUnique({ where: { id: 1, }, }) ``` **Mongoose** ```ts const result = await User.findById(1) ``` ## Fetching selected scalars of single objects **Prisma ORM** ```ts const user = await prisma.user.findUnique({ where: { id: 1, }, select: { name: true, }, }) ``` **Mongoose** ```ts const user = await User.findById(1).select(['name']) ``` ## Fetching relations **Prisma ORM** ```ts const userWithPost = await prisma.user.findUnique({ where: { id: 2, }, include: { post: true, }, }) ``` ```ts const userWithPost = await prisma.user .findUnique({ where: { id: 2, }, }) .post() ``` **Mongoose** ```ts const userWithPost = await User.findById(2).populate('post') ``` ## Filtering for concrete values **Prisma ORM** ```ts const posts = await prisma.post.findMany({ where: { title: { contains: 'Hello World', }, }, }) ``` **Mongoose** ```ts const posts = await Post.find({ title: 'Hello World', }) ``` ## Other filter criteria **Prisma ORM** Prisma ORM generates many [additional filters](/orm/prisma-client/queries/filtering-and-sorting) that are commonly used in modern application development. **Mongoose** Mongoose exposes the [MongoDB query selectors](https://www.mongodb.com/docs/manual/reference/operator/query/#query-selectors) as filter criteria. ## Relation filters **Prisma ORM** Prisma ORM lets you filter a list based on a criteria that applies not only to the models of the list being retrieved, but to a _relation_ of that model. For example, the following query returns users with one or more posts with "Hello" in the title: ```ts const posts = await prisma.user.findMany({ where: { Post: { some: { title: { contains: 'Hello', }, }, }, }, }) ``` **Mongoose** Mongoose doesn't offer a dedicated API for relation filters. You can get similar functionality by adding an additional step to filter the results returned by the query. ## Pagination **Prisma ORM** Cursor-style pagination: ```ts const page = prisma.post.findMany({ before: { id: 242, }, last: 20, }) ``` Offset pagination: ```ts const cc = prisma.post.findMany({ skip: 200, first: 20, }) ``` **Mongoose** ```ts const posts = await Post.find({ skip: 200, limit: 20, }) ``` ## Creating objects **Prisma ORM** ```ts const user = await prisma.user.create({ data: { name: 'Alice', email: 'alice@prisma.io', }, }) ``` **Mongoose** ```ts const user = await User.create({ name: 'Alice', email: 'alice@prisma.io', }) ``` ```ts const user = new User({ name: 'Alice', email: 'alice@prisma.io', }) await user.save() ``` ## Updating objects **Prisma ORM** ```ts const user = await prisma.user.update({ data: { name: 'Alicia', }, where: { id: 2, }, }) ``` **Mongoose** ```ts const updatedUser = await User.findOneAndUpdate( { _id: 2 }, { $set: { name: 'Alicia', }, } ) ``` ```ts user.name = 'Alicia' await user.save() ``` ## Deleting objects **Prisma ORM** ```ts const user = prisma.user.delete({ where: { id: 10, }, }) ``` **Mongoose** ```ts await User.deleteOne({ _id: 10 }) ``` ## Batch deletes **Prisma ORM** ```ts const users = await prisma.user.deleteMany({ where: { id: { in: [1, 2, 6, 6, 22, 21, 25], }, }, }) ``` **Mongoose** ```ts await User.deleteMany({ id: { $in: [1, 2, 6, 6, 22, 21, 25] } }) ``` --- # Drizzle URL: https://www.prisma.io/docs/orm/more/comparisons/prisma-and-drizzle Prisma and Drizzle take different approaches to working with databases. While Drizzle appeals to developers who prefer writing queries close to SQL, Prisma is designed to support teams building and maintaining production applications—where clarity, collaboration, and long-term maintainability matter. While both libraries solve similar problems, they work in very different ways and have individual pros and cons. Which one to choose will depend on the needs of your project and the exact tradeoffs that are important for it. ## Drizzle vs Prisma ORM **Drizzle** is a traditional SQL query builder that lets you compose SQL queries with JavaScript/TypeScript functions. It can be used to query a database or run migrations. Drizzle also offers a Queries API, which offers a higher level abstraction from SQL and can be used to read nested relations. Drizzle schema is defined in TypeScript files, which are used to generate SQL migrations and are then executed against a database. **Prisma ORM** mitigates many problems of traditional ORMs, such as bloated model instances, mixing business with storage logic, lack of type-safety or unpredictable queries caused e.g. by lazy loading. It uses the [Prisma schema](/orm/prisma-schema) to define application models in a declarative way. Prisma Migrate then allows the generation of SQL migrations from the Prisma schema and executes them against the database. CRUD queries are provided by Prisma Client, a lightweight and entirely type-safe database client for Node.js and TypeScript. ## Prisma: Built for Teams Prisma is designed to help teams ship faster—especially when not everyone is a SQL expert. * **No SQL bottlenecks**: With Prisma, you don’t need deep SQL knowledge to be productive. Your entire team can contribute to backend code—without relying on one person to write raw queries or debug database logic. * **Shared mental model**: Prisma’s schema is human-readable and easy to reason about. It provides a single, consistent view of your application’s data model. * **Easier code reviews**: Schema changes and data access patterns are transparent and consistent, making it easier for reviewers to understand and approve backend changes. * **Predictable workflows**: Prisma automates migration generation, client typing, and query construction—so your team doesn’t have to. Drizzle can be great in the hands of a single developer who knows SQL or prefers learning it. But once you have a team, Prisma removes the friction and knowledge risk that slows you down. ## Type safety Drizzle is not _fully_ type safe. As quoted on this [comparison study](https://github.com/thetutlage/meta/discussions/8) done by a 3rd party, "Drizzle gives the impression of type-safety. However, only the query results have type information. You can write invalid queries with Drizzle." With Prisma, you get _full_ type safety thanks to the generated types. This means, less potential for errors when writing code and collaborating with team members. ## Prisma Schema as a Single Source of Truth With Prisma, your data model lives in a single file: schema.prisma. * **It’s explicit**: No need to infer types or decipher SQL-generating functions—your schema is right there. * **It’s readable**: Even non-technical teammates can understand your models and relationships. * **It powers everything**: Migrations, TypeScript types, autocompletion, ERD generation, and more all come from your schema. In contrast, Drizzle’s schema is built via TypeScript code, which makes it harder to visualize your full data model, increases cognitive load, and can lead to inconsistencies in how models are defined across the codebase. [Read more](https://www.prisma.io/blog/prisma-schema-language-the-best-way-to-define-your-data) about why we are bullish on PSL (Prisma Schema Language). Want to see your schema as an ERD? With Prisma, it’s one command: `npx prisma generate && npx prisma-erd-generator` ## API design & Level of abstraction Drizzle and Prisma ORM operate on different levels of abstraction. Drizzle's philosophy is "If you know SQL, you know Drizzle ORM". It mirrors SQL in its API while Prisma Client provides a higher-level abstraction that was designed with the common tasks of application developers in mind. Prisma ORM's API design heavily leans on the idea of [making the right thing easy](https://jason.energy/right-thing-easy-thing/). While Prisma Client operates on a higher level of abstraction, you are able to drop down to [raw SQL](/orm/prisma-client/using-raw-sql) at any time. However, full use of Prisma ORM and development of your application does not require SQL knowledge. Prisma ORM's goal is to construct a query syntax focused on developer experience and productivity that feels familiar to developers. You can learn more about this here: [Why Prisma](/orm/overview/introduction/why-prisma#application-developers-should-care-about-data--not-sql). For the few queries that are unable to be expressed in the Prisma Client API, Prisma ORM also offers [TypedSQL](/orm/prisma-client/using-raw-sql/typedsql) which provides a more familiar and type-safe experience by directly utilizing `.sql` files. Your existing SQL tooling and workflow can work alongside Prisma Client to handle any level of abstraction desired. While fully typed SQL queries are available in Prisma ORM with TypedSQL, the following sections examine a few examples of how the Prisma and Drizzle APIs differ and what the rationale of Prisma ORM's API design is in these cases. ### Data modeling Prisma models are defined in the [Prisma schema](/orm/prisma-schema), while Drizzle uses TypeScript functions for table definitions. These functions are then exported and used in queries. Prisma generates a lightweight database client that exposes a tailored and fully type-safe API to read and write data for the models that are defined in the Prisma schema, following the DataMapper ORM pattern. Prisma ORM's DSL for data modeling is lean, simple and intuitive to use. When modeling data in VS Code, you can further take advantage of Prisma ORM's powerful [VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) with features like autocompletion, quick fixes, jump to definition and other benefits that increase developer productivity. On the other hand, Drizzle's use of TypeScript means that you can lean on the power of TypeScript for additional flexibility (via reused code, for example). ```prisma model User { id Int @id @default(autoincrement()) name String? email String @unique posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) authorId Int? author User? @relation(fields: [authorId], references: [id]) } ``` ```ts import { boolean, integer, pgTable, serial, text, uniqueIndex, varchar, } from 'drizzle-orm/pg-core' export const users = pgTable('users', { id: serial('id').primaryKey(), name: varchar('name', { length: 256 }), email: varchar('email', { length: 256 }).unique(), }) export const posts = pgTable('posts', { id: serial('id').primaryKey(), title: varchar('title', { length: 256 }).notNull(), content: text('content'), published: boolean('published'), authorId: integer('author_id').references(() => users.id), }) ``` ### Migrations Migrations work similarly between Drizzle and Prisma ORM. Both tools follow the approach of generating SQL files based on the provided model definitions and provide a CLI to execute them against the database. The SQL files can be modified before the migrations are executed so that any custom database operation can be performed with either migration system. ### Querying Plain queries are natural to construct in both Drizzle and Prisma ORM. Using Drizzle's Queries API, the two approaches are very similar: ```ts // find all users const allUsers = await prisma.user.findMany() // find a single user const user = await prisma.user.findFirst({ where: { id: 27 }, }) // find a unique user const user = await prisma.user.findUnique({ where: { email: 'nilu@prisma.io' }, }) ``` ```ts import { eq } from 'drizzle-orm' // find all users const allUsers = await db.query.users.findMany() // find a single user const user = await db.query.users.findFirst({ where: eq(users.id, 1), }) // find a unique post const user = await db.query.users.findFirst({ where: eq(users.email, 'nilu@prisma.io'), }) ``` When performing a mutation, a `create`, `update`, or `delete`, the Drizzle Queries API is not available. In these cases, you will need to use Drizzle's SQL-like APIs: ```ts // create a user const user = await prisma.user.create({ data: { name: 'Nilu', email: 'nilu@prisma.io', }, }) // update a user const user = await prisma.user.update({ where: { email: 'nilu@prisma.io' }, data: { name: 'Another Nilu' }, }) // delete a user const deletedUser = await prisma.user.delete({ where: { email: 'nilu@prisma.io' }, }) ``` ```ts // create a user const user = await db.insert(users).values({ name: 'Nilu', email: 'nilu@prisma.io', }) // update a user const user = await db .update(users) .set({ name: 'Another Nilu' }) .where(eq(users.email, 'nilu@prisma.io')) .returning() // delete a user const deletedUser = await db .delete(users) .where(eq(users.email, 'nilu@prisma.io')) .returning() ``` ### Relations Working with records that are connected via foreign keys can become very complex in SQL. Prisma ORM's concept of [virtual relation field](/orm/prisma-schema/data-model/relations#relation-fields) enables an intuitive and convenient way for application developers to work with related data. Some benefits of Prisma ORM's approach are: - traversing relationships via the fluent API ([docs](/orm/prisma-client/queries/relation-queries#fluent-api)) - nested writes that enable updating/creating connected records ([docs](/orm/prisma-client/queries/relation-queries#nested-writes)) - applying filters on related records ([docs](/orm/prisma-client/queries/relation-queries#relation-filters)) - easy and type-safe querying of nested data without worrying about underlying SQL ([docs](/orm/prisma-client/queries/relation-queries#nested-reads)) - creating nested TypeScript typings based on models and their relations ([docs](/orm/prisma-client/type-safety)) - intuitive modeling of relations in the data model via relation fields ([docs](/orm/prisma-schema/data-model/relations)) - implicit handling of relation tables (also sometimes called JOIN, link, pivot or junction tables) ([docs](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations)) ```ts const posts = await prisma.post.findMany({ include: { author: true, }, }) ``` ```ts const posts = await db.query.posts.findMany({ with: { author: true, }, }) ``` ### Filtering Drizzle exposes the underlying filter and conditional operators for a given SQL dialect. Prisma ORM on the other hand, provides a more [generic set of operators](/orm/prisma-client/queries/filtering-and-sorting#filter-conditions-and-operators) that are intuitive to use. A good example of how the filtering APIs of both Drizzle and Prisma ORM differ is by looking at `string` filters. While Drizzle provides filters for `like` and `ilike`, Prisma ORM provides more specific operators that developers can use, e.g.: `contains`, `startsWith` and `endsWith`. ```ts // case sensitive filter const posts = await prisma.post.findMany({ where: { title: 'Hello World', }, }) // case insensitive filter const posts = await prisma.post.findMany({ where: { title: 'Hello World', mode: 'insensitive', }, }) ``` ```ts // case sensitive filter const posts = await db .select() .from(posts) .where(like(posts.title, 'Hello World')) // case insensitive filter const posts = await db .select() .from(posts) .where(ilike(posts.title, 'Hello World')) ``` ```ts const posts = await prisma.post.findMany({ where: { title: { contains: 'Hello World', }, }, }) ``` ```ts const posts = await db .select() .from(posts) .where(ilike(posts.title, '%Hello World%')) ``` ```ts const posts = await prisma.post.findMany({ where: { title: { startsWith: 'Hello World', }, }, }) ``` ```ts const posts = await db .select() .from(posts) .where(ilike(posts.title, 'Hello World%')) ``` ```ts const posts = await prisma.post.findMany({ where: { title: { endsWith: 'Hello World', }, }, }) ``` ```ts const posts = await db .select() .from(posts) .where(ilike(posts.title, '%Hello World')) ``` ### Observability Both Drizzle and Prisma ORM have the ability to log queries and the underlying SQL generated. Prisma ORM has additional features built into the client that help teams get a better understanding of their data usage. [Metrics](/orm/prisma-client/observability-and-logging/metrics) and [tracing](/orm/prisma-client/observability-and-logging/opentelemetry-tracing) are two features that can be enabled at any time and give you per query information. This information can be integrated with external tools so that you can track performance over time. ## Additional products Both Drizzle and Prisma offer products alongside an ORM. Prisma Studio was released to allow users to interact with their database via a GUI and also allows for limited self-hosting for use within a team. Drizzle Studio was released to accomplish the same tasks. In addition to Prisma Studio, Prisma offers commercial products via the Prisma Data Platform: - [Prisma Accelerate](https://www.prisma.io/accelerate?utm_source=docs&utm_medium=orm-docs): A connection pooler and global cache that integrates with Prisma ORM. Users can take advantage of connection pooling immediately and can control caching at an individual query level. - [Prisma Optimize](https://www.prisma.io/optimize?utm_source=docs&utm_medium=orm-docs): A query analytics tool that provides deep insights, actionable recommendations, and allows you to interact with Prisma AI for further insights and optimizing your database queries. These products work hand-in-hand with Prisma ORM to offer comprehensive data tooling, making building data-driven applications easy by following [Data DX](https://www.datadx.io/) principles. ## Safer Changes and Fewer Bugs Prisma minimizes the risk of human error when working with your database. * **Renaming a field?** Prisma updates the schema, the database, and the generated client. You stay in sync automatically. * **Changing a relationship?** Prisma generates a safe migration and enforces correctness via full type safety. Teams choose Prisma because it enforces correctness and helps you move fast without breaking things. ## Batteries-Included Ecosystem Both Drizzle and Prisma ORM have cases where users want to do something not directly supported by the library. Drizzle relies on the expressiveness of SQL to avoid these cases, while Prisma ORM has [Prisma Client extensions](/orm/prisma-client/client-extensions) to allow any user to add additional behaviors to their instance of Prisma Client. These extensions are also shareable, meaning teams can develop them for use across their projects or even for use by other teams. While Drizzle is a relatively new product, Prisma ORM was [released in 2021](https://www.prisma.io/blog/how-prisma-orm-became-the-most-downloaded-orm-for-node-js) and is well established in the JavaScript/TypeScript space. It has proven value and many companies trust [Prisma ORM in production](https://www.prisma.io/showcase). Prisma ORM is also included as the data layer tool of choice in many meta-frameworks and development platforms like [Amplication](https://amplication.com/), [Wasp](https://wasp.sh/), [RedwoodJS](https://rwsdk.com/), [KeystoneJS](https://keystonejs.com/), [Remix](https://remix.run/) and the [t3 stack](https://create.t3.gg/). Thanks to its maturity, Prisma's community has developed a [plethora of useful tools](https://www.prisma.io/ecosystem) that helps with various Prisma workflows. Here are a few highlights: - [`prisma-erd-generator`](https://github.com/keonik/prisma-erd-generator#prisma-entity-relationship-diagram-generator): Visualizes the Prisma schema as an entity-relationship-diagram (ERD). - [`prisma-zod-generator`](https://github.com/omar-dulaimi/prisma-zod-generator): Generates [Zod](https://github.com/colinhacks/zod) schemas from the Prisma schema. - [`bridg`](https://github.com/bridg-db/bridg): Let's you access your database from the frontend using Prisma Client. - [`jest-prisma`](https://github.com/Quramy/jest-prisma): Environment for Prisma integrated testing with [Jest](https://jestjs.io/). - [`prisma-pothos-types`](https://github.com/hayes/pothos/tree/main/packages/plugin-prisma): Creates GraphQL types based on Prisma models when using [GraphQL Pothos](https://github.com/hayes/pothos/tree/main). - [`prisma-trpc-generator`](https://github.com/omar-dulaimi/prisma-trpc-generator): Creates [tRPC](https://trpc.io/) routers from your Prisma schema. - [`@cerbos/orm-prisma`](https://github.com/cerbos/query-plan-adapters/tree/main/prisma): Filter data based on authorization policies from [Cerbos](https://www.cerbos.dev). Prisma isn’t just an ORM—it’s a complete type-safe data toolkit: * Prisma Schema → migrations, types, and documentation * Prisma Client → auto-completed, fully type-safe queries * Prisma Studio → a [GUI](https://prisma.io/studio) to inspect and edit data * Native integrations → PlanetScale, Vercel, Cloudflare D1, Neon, and more ## Database support Both Drizzle and Prisma ORM support multiple and different kinds of databases. Drizzle achieves this support through driver implementations created by Drizzle, which integrate with existing third-party database drivers. Prisma ORM has begun adding support for [third-party database drivers](https://www.prisma.io/blog/serverless-database-drivers-KML1ehXORxZV), but primarily uses [built-in drivers](/orm/more/under-the-hood/engines#the-query-engine-at-runtime) to communicate with an underlying database. Prisma also defaults connections to TLS, which improves security. Additionally, Prisma ORM supports CockroachDB, Microsoft SQL Server, and MongoDB, which Drizzle does not currently support. Prisma ORM also offers the [relation mode](/orm/prisma-schema/data-model/relations/relation-mode) that allows Prisma ORM to emulate foreign key constraints for those database engines that do not support it. Drizzle currently supports Cloudflare D1, `bun:sqlite`, and SQLite via HTTP Proxy, which Prisma ORM currently does not. ## Benchmarks We understand that performance is a key consideration when selecting an ORM. To compare performance of various ORMs, you can use the open-source [database latency benchmark tool](https://pris.ly/benchmark) hosted by Vercel. This tool allows you to evaluate the latency and throughput of various ORMs under different workloads and configurations. By running the benchmarks against the databases or database providers you are considering, you can get a clear picture of their relative performance characteristics to help make an informed decision. Alternatively, you can also review findings on the [benchmark tool](https://benchmarks.prisma.io) that we have built that compares popular TypeScript ORMs, including Drizzle. This benchmark is open source and aims to be a fair comparison of database query latencies across database providers and ORM libraries in the Node.js and TypeScript ecosystem. ## Conclusion Yes, we are biased, but this is also what we have heard from our users and customers: * "We switched from Drizzle to Prisma because schema drift was killing us. Prisma just works." * "I onboarded a junior dev in 2 hours thanks to Prisma’s schema. With Drizzle, it would’ve taken days." * "I trust Prisma to keep our database sane. No one on our team needs to be a Postgres expert." * "The pace of updates and new features from the Prisma team has been nothing short of outstanding." Both Drizzle ORM and Prisma ORM are tools for data access and migrations. Drizzle is focused on being a thin wrapper around a SQL-like syntax while Prisma is focused on a convenient and expressive API. Other important differences include Prisma ORM's support of MSSQL and MongoDB, support for additional features via [Prisma Client extensions](/orm/prisma-client/client-extensions), additional cloud-ready products, and a robust ecosystem. On the other hand, for teams that are a mix of developers (front-end, back-end, and full-stack) that have varying levels of experience with databases, Prisma ORM offers a comprehensive and easy-to-learn approach for data access and managing database schemas. --- # Comparing Prisma ORM URL: https://www.prisma.io/docs/orm/more/comparisons/index Find out how Prisma ORM compares to ORMs and ODMs in the Node.js and TypeScript ecosystem. For a comprehensive overview of the most popular database libraries, read this article: [Top Node.js ORMs, Query Builders & Database Libraries in 2022](https://www.prisma.io/dataguide/database-tools/top-nodejs-orms-query-builders-and-database-libraries). ## In this section --- # Managing Prisma ORM environment variables and settings URL: https://www.prisma.io/docs/orm/more/development-environment/environment-variables An environment variable is a key value pair of string data that is stored on your machine's local environment. Refer to our [Environment variables reference documentation](/orm/reference/environment-variables-reference) for specific details. Typically the name of the variable is uppercase, this is then followed by an equals sign then the value of the variable: ```env MY_VALUE=prisma ``` The environment variable belongs to the environment where a process is running.Any program can read and create these environment variables. They are a cheap and effective way to store simple information. :::tip With Prisma ORM v6.4.0, we released the `prisma.config.ts` file into Early Access. This file allows you to manage your environment variables and settings in a more flexible way. [View our reference](/orm/reference/prisma-config-reference) for more information and don't forget to [share your feedback](https://github.com/prisma/prisma/discussions/new?category=feedback) in our GitHub discussions! ::: ## How Prisma ORM can use environment variables Prisma ORM always reads environment variables from the system's environment. When you initialize Prisma ORM in your project with `prisma init`, it creates a convenience `.env` file for you to set your [`connection url`](/orm/reference/connection-urls) as an environment variable. When you use Prisma CLI or Prisma Client, the `.env` file content and the variables defined in it are added to the [`process.env` object](https://nodejs.org/api/process.html#processenv), where Prisma ORM can read it and use it. ### Using an `.env` file :::warning **Do not commit your `.env` files into version control**! ::: The Prisma CLI looks for `.env` files, in order, in the following locations: 1. In the root folder of your project (`./.env`) 1. From the same folder as the schema specified by the `--schema` argument 1. From the same folder as the schema taken from `"prisma": {"schema": "/path/to/schema.prisma"}` in `package.json` 1. From the `./prisma` folder If a `.env` file is located in step 1., but additional, clashing `.env` variables are located in steps 2. - 4., the CLI will throw an error. For example, if you specify a `DATABASE_URL` variable in two different `.env` files, you will get the following error: ``` Error: There is a conflict between env vars in .env and prisma/.env Conflicting env vars: DATABASE_URL We suggest to move the contents of prisma/.env to .env to consolidate your env vars. ``` The following table describes where the Prisma CLI looks for the `.env` file: | **Command** | **schema location** | **`.env` file locations checked, in order** | | :---------------------------------------------- | :--------------------------------------------------------------------------- | :-------------------------------------------------------- | | `prisma [command]` | `./prisma/schema.prisma` | `./.env`
`./prisma/.env` | | `prisma [command] --schema=./a/b/schema.prisma` | `./a/b/schema.prisma` | `./.env`
`./a/b/.env`
`./prisma/.env` | | `prisma [command]` | `"prisma": {"schema": "/path/to/schema.prisma"}` | `.env`
`./path/to/schema/.env`
`./prisma/.env` | | `prisma [command]` | No schema (for example, when running `prisma db pull` in an empty directory) | `./.env`
`./prisma/.env` | Any environment variables defined in that `.env` file will automatically be loaded when running a Prisma CLI command. :::info Looking to use more than one `.env` file? See [Using multiple `.env` files](#using-multiple-env-files) for information on how to setup and use multiple `.env` files in your application. ::: Refer to the `dotenv` documentation for information about [what happens if an environment variable is defined in two places](https://www.npmjs.com/package/dotenv#what-happens-to-environment-variables-that-were-already-set). #### Expanding variables with `.env` files Variables stored in `.env` files can be expanded using the format specified by [dotenv-expand](https://github.com/motdotla/dotenv-expand). ```env file=.env DATABASE_URL=postgresql://test:test@localhost:5432/test DATABASE_URL_WITH_SCHEMA=${DATABASE_URL}?schema=public ``` Additionally, you can use environment variables in the expansion that are set _outside_ of the `.env` file. For example a database URL that is set on a PaaS like Heroku or similar: ```terminal # environment variable already set in the environment of the system export DATABASE_URL=postgresql://test:test@localhost:5432/test ``` ```env file=.env DATABASE_URL_WITH_SCHEMA=${DATABASE_URL}?schema=foo ``` This will make the environment variable `DATABASE_URL_WITH_SCHEMA` with value `postgresql://test:test@localhost:5432/test?schema=foo` available for Prisma ORM. ### Using environment variables in your code If you want environment variables to be evaluated at runtime, you need to load them manually in your application code (for example, by using [`dotenv`](https://github.com/motdotla/dotenv)): ```ts import * as dotenv from 'dotenv' dotenv.config() // Load the environment variables console.log(`The connection URL is ${process.env.DATABASE_URL}`) ``` If you are using a custom file name for your environment variables, you can configure `dotenv` to use that filename: ```ts import * as dotenv from 'dotenv' var envFile = path.resolve(join(__dirname, "myenv.env")) dotenv.config({path: envFile}) // Load the environment variables console.log(`The connection URL is ${process.env.DATABASE_URL}`) ``` If you need variable expansion across environment files, you can additionally use [`dotenv-expand`](https://github.com/motdotla/dotenv-expand): ```ts import * as dotenv from 'dotenv' const dotenvExpand = require('dotenv-expand') var envFile = path.resolve(join(__dirname, "myenv.env")) var mySqlEnv = dotenv.config({path: envFile}) dotenvExpand.expand(mySqlEnv) ``` If you are using multiple `.env` files, you can refernce an environment file in your project's code depending on the environment you are running in. ```ts import { config } from 'dotenv' const envFile = process.env.NODE_ENV === 'development' ? '.env.development' : '.env.production' config({ path: envFile }) ``` ### Manually set environment variables Because Prisma ORM reads from the system's environment when looking for environment variables, it's possible to skip using `.env` completely and create them manually on your local system. :::info The following examples will use setting the `DATABASE_URL` environment variable which is often used for the database connection URL. ::: #### Manually set an environment variable on a Mac/Linux system From a terminal on a Unix machine (Mac/Linux), you export the variable as a key value pair. ```terminal export DATABASE_URL=postgresql://test:test@localhost:5432/test?schema=public ``` Then check that it has been successfully set using `printenv`: ```terminal printenv DATABASE_URL ``` ```code no-copy postgresql://test:test@localhost:5432/test?schema=public ``` #### Manually set an environment variable on a Windows system The following examples illustrate how to set the environment variable (for the current user) using both Command Prompt (`cmd.exe`) and PowerShell, depending on your preference. ```terminal set DATABASE_URL="postgresql://test:test@localhost:5432/test?schema=public" ``` ```terminal [Environment]::SetEnvironmentVariable("DATABASE_URL", "postgresql://test:test@localhost:5432/test?schema=public") ``` Then check that it has been successfully set: ```terminal set DATABASE_URL ``` ```terminal Get-ChildItem Env:DATABASE_URL ``` ### Using multiple `.env` files There is a risk that your production database could be deleted if you store different connection URLs to each of your environments within a single `.env` file. One solution is to have multiple `.env` files which each represent different environments. In practice, this means you create a file for each of your environments: - `.env.development` - `.env.sample` Then using a package like [`dotenv-cli`](https://www.npmjs.com/package/dotenv-cli), you can load the correct connection URL for the environment you are working in. :::info For our purposes, it is assumed you have a dedicated development database that you use while developing your application. ::: 1. Rename your `.env` file to `.env.development` ```env file=.env.development DATABASE_URL="postgresql://prisma:prisma@localhost:5433/dev" ``` 2. Create a new `.env.sample` file and change the database name to `sample` (or your preferred name) ```env file=.env.sample DATABASE_URL="postgresql://prisma:prisma@localhost:5433/sample" ``` 3. Install [`dotenv-cli`](https://www.npmjs.com/package/dotenv-cli) In order for Prisma ORM and Jest to know which `.env` file to use, alter your `package.json` scripts to include and call the `dotenv` package and specify which file to use depending on what commands you are running and in which environment you want them to run. :::info Any top-level script that is running the tests and migrations needs the `dotenv` command before it. This makes sure that the env variables from `.env.sample` are passed to all commands, including Jest. ::: #### Running migrations on different environments You can use the [`dotenv-cli`](https://www.npmjs.com/package/dotenv-cli) package to specify which environment file Prisma ORM should use when running a migration. The below script uses `dotenv-cli` to pass the `.env.sample` environment file (which holds a `DATABASE_URL` connection string) to the Prisma ORM migration script. #### Migration script ```json file=package.json "scripts": { "migrate:postgres": "dotenv -e .env.sample -- npx prisma migrate deploy", }, ``` #### Running tests on different environments When running tests, we advise you to [mock Prisma Client](/orm/prisma-client/testing/unit-testing#mocking-prisma-client). In doing so, you need to tell Jest which environment it should use when running its tests. By default, Prisma Client will use the environment specified in the default `.env` file located at the project's root. If you have created a separate `.env.sample` file to specify your testing database, then this environment will need to be passed to Jest. The below script uses `dotenv-cli` to pass the `.env.sample` environment file (which holds a `DATABASE_URL` connection string) to Jest. ```json file=package.json "scripts": { "test": "dotenv -e .env.sample -- jest -i" }, ``` --- # Editor setup URL: https://www.prisma.io/docs/orm/more/development-environment/editor-setup This page describes how you can configure your editor for an optimal developer experience when using Prisma ORM. If you don't see your editor here, please [open a feature request](https://github.com/prisma/prisma/issues/new?assignees=&labels=&template=feature_request.md&title=) and ask for dedicated support for your editor (e.g. for syntax highlighting and auto-formatting). ## VS Code You can install the official [Prisma VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma). Once installed, make sure to select the appropriate language model to use it within VS Code. ## Community projects > **Note**: Community projects are not maintained or officially supported by Prisma and some features may by out of sync. Use at your own discretion. ### Emacs - [emacs-prisma-mode](https://github.com/pimeys/emacs-prisma-mode) provides syntax highlighting of the Prisma Schema Language and uses the Prisma Language Server. ### Vim - [vim-prisma](https://github.com/prisma/vim-prisma) provides file detection and syntax highlighting of the Prisma Schema Language. ### neovim - [coc-prisma](https://github.com/pantharshit00/coc-prisma) implements the Prisma Language Server. ### JetBrains IDE - [Prisma ORM](https://plugins.jetbrains.com/plugin/20686-prisma-orm) Provided by JetBrains. This plugin provides PSL grammar, syntax highlighting, LSP, and more. ### Sublime Text - [Prisma](https://packagecontrol.io/packages/Prisma) - For Sublime Text 3 & 4 - Provides syntax highlighting for the Prisma Schema Language. ([Source Code](https://github.com/Sublime-Instincts/PrismaHighlight/)) - [LSP-prisma](https://packagecontrol.io/packages/LSP-prisma) - For Sublime Text 4 - Language Server helper package for Prisma schema files that uses Prisma's Language Server to provide linting, error checking, formatting, autocompletion, renaming etc. Note: It requires the Prisma package to be installed. ([Source Code](https://github.com/Sublime-Instincts/LSP-prisma)) ### nova - [nova](https://extensions.panic.com/extensions/robb-j/robb-j.Prisma/) provides syntax highlighting of the Prisma Schema Language and uses the Prisma Language Server. ### Helix - [Helix](https://helix-editor.com/) (from version 22.08) provides syntax highlighting of the Prisma Schema Language and uses the Prisma Language Server. ### CLI autocomplete #### inshellisense You can get IDE-style autocompletion for Prisma CLI using [`inshellisense`](https://github.com/microsoft/inshellisense/tree/main). It supports: bash, zsh, fish, pwsh, powershell (Windows Powershell). To install, run: ```bash npm install -g @microsoft/inshellisense ``` #### Fig `inshellisense` is built on top of [Fig](https://fig.io/) which you can also use directly. It works in bash, zsh, and fish. To install, run: ```bash brew install fig ``` --- # Development environment URL: https://www.prisma.io/docs/orm/more/development-environment/index This section describes using `env` variables, editors, and workspaces in your development environment. ## In this section --- # Autocompletion in GraphQL resolvers with JavaScript URL: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/autocompletion-in-graphql-resolvers-with-js ## Problem When using GraphQL with TypeScript, you always get autocompletion for the Prisma Client instance in your GraphQL resolvers because then the `context` object can be typed – no matter if folks are using Nexus, TypeGraphQL or SDL first. This immensely helps with autocompletion and preventing unwanted errors. Unfortunately, this needs a little more effort when you're working in plain JavaScript. Suppose we have a resolver like this: ```js filterPosts: (parent, args, ctx) => { return ctx.prisma.post.findMany({ where: { OR: [ { title: { contains: args.searchString } }, { content: { contains: args.searchString } }, ], }, }) } ``` Now whenever you type `ctx.` VS Code will provide unnecessary options in the autocomplete which is undesirable. ![Unwanted autocomplete values by VSCode](/img/orm/unwanted-autocomplete-values-in-vscode.png) VS Code doesn't know the _type_ of the `context` object so it can't provide any intellisense for it, which is why unwanted suggestions are displayed. ## Solution To overcome this, you need to add a [JSDoc](https://jsdoc.app/) comment named `typedef` to "import" the correct type of your `PrismaClient` instance. ```js // Add this to the top of the file /** * @typedef { import("@prisma/client").PrismaClient } Prisma */ ``` > **Note**: You can learn more about JSDoc [here](https://devhints.io/jsdoc). Finally, you need to type your resolver arguments. For simplicity, ignore the `parent` and `args` parameters. So the resolver should now look like this: ```js /** * @param {any} parent * @param {{ searchString: string }} args * @param {{ prisma: Prisma }} ctx */ filterPosts: (parent, args, ctx) => { return ctx.prisma.post.findMany({ where: { OR: [ { title: { contains: args.searchString } }, { content: { contains: args.searchString } }, ], }, }) } ``` This will tell VS Code that the `context` has a property named `prisma` and the type is `Prisma` which was defined in the `@typedef` above. And voilà, autocompletion in plain JavaScript. ![The correct parameters for context are obtained](/img/orm/prisma-autocompletion-in-js.png) The final file should look something like: ```js /** * @typedef { import("@prisma/client").PrismaClient } Prisma * @typedef { import("@prisma/client").UserCreateArgs } UserCreateArgs */ const { makeExecutableSchema } = require('graphql-tools') const typeDefs = ` type User { email: String! id: ID! name: String posts: [Post!]! } type Post { author: User content: String id: ID! published: Boolean! title: String! } type Query { feed: [Post!]! filterPosts(searchString: String): [Post!]! post(where: PostWhereUniqueInput!): Post } type Mutation { createDraft(authorEmail: String, content: String, title: String!): Post! deleteOnePost(where: PostWhereUniqueInput!): Post publish(id: ID): Post signupUser(data: UserCreateInput!): User! } input PostWhereUniqueInput { id: ID } input UserCreateInput { email: String! id: ID name: String posts: PostCreateManyWithoutPostsInput } input PostCreateManyWithoutPostsInput { connect: [PostWhereUniqueInput!] create: [PostCreateWithoutAuthorInput!] } input PostCreateWithoutAuthorInput { content: String id: ID published: Boolean title: String! } ` const resolvers = { Query: { /** * @param {any} parent * @param {any} args * @param {{ prisma: Prisma }} ctx */ feed: (parent, args, ctx) => { return ctx.prisma.post.findMany({ where: { published: true }, }) }, /** * @param {any} parent * @param {{ searchString: string }} args * @param {{ prisma: Prisma }} ctx */ filterPosts: (parent, args, ctx) => { return ctx.prisma.post.findMany({ where: { OR: [ { title: { contains: args.searchString } }, { content: { contains: args.searchString } }, ], }, }) }, /** * @param {any} parent * @param {{ where: { id: string }}} args * @param {{ prisma: Prisma }} ctx */ post: (parent, args, ctx) => { return ctx.prisma.post.findUnique({ where: { id: Number(args.where.id) }, }) }, }, Mutation: { /** * @param {any} parent * @param {{ title: string, content: string, authorEmail: (string|undefined) }} args * @param {{ prisma: Prisma }} ctx */ createDraft: (parent, args, ctx) => { return ctx.prisma.post.create({ data: { title: args.title, content: args.content, published: false, author: args.authorEmail && { connect: { email: args.authorEmail }, }, }, }) }, /** * @param {any} parent * @param {{ where: { id: string }}} args * @param {{ prisma: Prisma }} ctx */ deleteOnePost: (parent, args, ctx) => { return ctx.prisma.post.delete({ where: { id: Number(args.where.id) }, }) }, /** * @param {any} parent * @param {{ id: string }} args * @param {{ prisma: Prisma }} ctx */ publish: (parent, args, ctx) => { return ctx.prisma.post.update({ where: { id: Number(args.id) }, data: { published: true }, }) }, /** * @param {any} parent * @param {UserCreateArgs} args * @param {{ prisma: Prisma }} ctx */ signupUser: (parent, args, ctx) => { return ctx.prisma.user.create(args) }, }, User: { /** * @param {{ id: number }} parent * @param {any} args * @param {{ prisma: Prisma }} ctx */ posts: (parent, args, ctx) => { return ctx.prisma.user .findUnique({ where: { id: parent.id }, }) .posts() }, }, Post: { /** * @param {{ id: number }} parent * @param {any} args * @param {{ prisma: Prisma }} ctx */ author: (parent, args, ctx) => { return ctx.prisma.post .findUnique({ where: { id: parent.id }, }) .author() }, }, } const schema = makeExecutableSchema({ resolvers, typeDefs, }) module.exports = { schema, } ``` --- # Modeling and querying many-to-many relations URL: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/working-with-many-to-many-relations ## Problem Modeling and querying many-to-many relations in relational databases can be challenging. This article shows two examples how this can be approached with Prisma ORM. The first example uses an [implicit](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations) and the second one uses an [explicit](/orm/prisma-schema/data-model/relations/many-to-many-relations#explicit-many-to-many-relations) many-to-many relation. ## Solution ### Implicit relations This is a type of many-to-many relation where Prisma ORM handles the [relation table](/orm/prisma-schema/data-model/relations/many-to-many-relations#relation-tables) internally. A basic example for an implicit many-to-many relation would look like this: ```prisma model Post { id Int @id @default(autoincrement()) title String tags Tag[] } model Tag { id Int @id @default(autoincrement()) name String @unique posts Post[] } ``` To create a post and its tags, one can write this with Prisma Client: ```ts await prisma.post.create({ data: { title: 'Types of relations', tags: { create: [{ name: 'dev' }, { name: 'prisma' }] }, }, }) ``` In the above example, we can directly query for posts along with their tags as follows: ```ts await prisma.post.findMany({ include: { tags: true }, }) ``` And the response obtained would be: ```json [ { "id": 1, "title": "Types of relations", "tags": [ { "id": 1, "name": "dev" }, { "id": 2, "name": "prisma" } ] } ] ``` Another use case for this is if you want to add new tags as well as connect to existing tags to a post. An example for this is where a user has created new tags for their post and has also selected existing tags to be added as well. In this case, we can perform this in the following way: ```ts await prisma.post.update({ where: { id: 1 }, data: { title: 'Prisma is awesome!', tags: { set: [{ id: 1 }, { id: 2 }], create: { name: 'typescript' } }, }, }) ``` ### Explicit relations Explicit relations mostly need to be created in cases where you need to store extra fields in the relation table or if you're [introspecting](/orm/prisma-schema/introspection) an existing database that already has many-to-many relations setup. This is the same schema used above but with an explicit relation table: ```prisma model Post { id Int @id @default(autoincrement()) title String tags PostTags[] } model PostTags { id Int @id @default(autoincrement()) post Post? @relation(fields: [postId], references: [id]) tag Tag? @relation(fields: [tagId], references: [id]) postId Int? tagId Int? @@index([postId, tagId]) } model Tag { id Int @id @default(autoincrement()) name String @unique posts PostTags[] } ``` Adding tags to a post would be a create into the relation table (`PostTags`) as well as into the tags table (`Tag`): ```ts await prisma.post.create({ data: { title: 'Types of relations', tags: { create: [ { tag: { create: { name: 'dev' } } }, { tag: { create: { name: 'prisma' } } }, ], }, }, }) ``` Also querying for posts along with their tags would require an extra `include` as follows: ```ts await prisma.post.findMany({ include: { tags: { include: { tag: true } } }, }) ``` This will provide the following output: ```json [ { "id": 1, "title": "Types of relations", "tags": [ { "id": 1, "postId": 1, "tagId": 1, "tag": { "id": 1, "name": "prisma" } }, { "id": 2, "postId": 1, "tagId": 2, "tag": { "id": 2, "name": "dev" } } ] } ] ``` Sometimes, it's not ideal to show the data for the relation table in your UI. In this case, it's best to map the data after fetching it on the server itself and sending that response to the frontend. ```ts const result = posts.map((post) => { return { ...post, tags: post.tags.map((tag) => tag.tag) } }) ``` This will provide an output similar to the one you received with implicit relations. ```json [ { "id": 1, "title": "Types of relations", "tags": [ { "id": 1, "name": "prisma" }, { "id": 2, "name": "dev" } ] } ] ``` This article showed how you can implement implicit and explicit many-to-many relations and query them using Prisma Client. --- # Converting Implicit many-to-many relation to Explicit many-to-many relation URL: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/implicit-to-explicit-conversion ## Problem Many-to-many relationships are an important aspect of relational databases, allowing multiple records in one table to be related to multiple records in another table. Prisma provides two approaches to model many-to-many relationships: [implicit](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations) and [explicit](/orm/prisma-schema/data-model/relations/many-to-many-relations#explicit-many-to-many-relations). Users sometimes encounter situations where they need to transition from implicit many-to-many relationships between models to explicit ones. Converting an implicit relation to explicit allows you to have more control over the relationship and store additional data specific to the relation, such as a timestamp or any other fields. This guide provides a step-by-step walkthrough on how to make that conversion. ## Solution This will guide you through the process of converting an implicit many-to-many relation to an explicit one in Prisma: Consider these models with an implicit many-to-many relationship via the `posts` and `author` fields: ```prisma model User { id Int @id @default(autoincrement()) name String posts Post[] } model Post { id Int @id @default(autoincrement()) title String authors User[] } ``` In the above models, a `User` can have multiple posts and a `Post` can have multiple authors. To convert the implicit relation to an explicit one, we need to create a [relation table](/orm/prisma-schema/data-model/relations/many-to-many-relations#relation-tables). The relation table will contain foreign keys referencing both tables involved in the many-to-many relation. In our example, we'll create a new model called `UserPost`. Our updated `schema.prisma` file would look like this: ```prisma highlight=15-24;add model User { id Int @id @default(autoincrement()) name String posts Post[] userPosts UserPost[] } model Post { id Int @id @default(autoincrement()) title String authors User[] userPosts UserPost[] } model UserPost { id Int @id @default(autoincrement()) userId Int postId Int user User @relation(fields: [userId], references: [id]) post Post @relation(fields: [postId], references: [id]) createdAt DateTime @default(now()) @@unique([userId, postId]) } ``` If you are using Prisma Migrate, then you can invoke this command: ```terminal npx prisma migrate dev --name "added explicit relation" ``` The migration will create the `UserPost` table and create one-to-many relation of `User` and `Post` model with `UserPost` model. ### Migrating Existing data from implicit relation table to newly created relation table To migrate the existing data from the implicit relation table to the new explicit relation table, you'll need to write a custom migration script. You can use the Prisma Client to interact with the database, read data from the implicit relation table, and write it to the new relation table. Considering the above `User` and `Post` models, here’s an example script you can use to migrate data. ```typescript import { PrismaClient } from "@prisma/client"; const prisma = new PrismaClient(); // A `main` function so that you can use async/await async function main() { try { // Fetch all users with their related posts const users = await prisma.user.findMany({ include: { posts: true }, }); // Iterate over users and their posts, then insert records into the UserPost table for (const user of users) { for (const post of user.posts) { await prisma.userPost.create({ data: { userId: user.id, postId: post.id, }, }); } } console.log("Data migration completed."); } catch (e) { console.error(e); } } main() .catch((e) => { throw e; }) .finally(async () => { await prisma.$disconnect(); }); ``` Once the data is migrated to the relation table, you can remove the implicit relation columns ( `posts` in `User` model and `author` in `Post` model ) as shown below: ```prisma highlight=4,11;delete model User { id Int @id @default(autoincrement()) name String posts Post[] userPosts UserPost[] } model Post { id Int @id @default(autoincrement()) title String authors User[] userPosts UserPost[] } ``` After making the change in schema file, you can invoke this command: ```terminal npx prisma migrate dev --name "removed implicit relation" ``` Running the above command would drop the implicit table `_PostToUser` You've now successfully converted an implicit many-to-many relation to an explicit one in Prisma. --- # Comprehensive Guide to Using Prisma ORM with Next.js URL: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/nextjs-help Prisma ORM and Next.js form a powerful combination for building modern, server-side rendered, and API-driven web applications. This guide consolidates various tips and strategies to help you maximize their potential. Whether you’re looking for best practices, monorepo setup guidance, or strategies for dynamic usage, we’ve got you covered. --- ## Best practices for using Prisma Client in development ### Avoid multiple Prisma Client instances When developing a Next.js application, one common issue is accidentally creating multiple instances of the Prisma Client. This often occurs due to Next.js’s hot-reloading feature in development. #### Why this happens Next.js’s hot-reloading feature reloads modules frequently to reflect code changes instantly. However, this can lead to multiple instances of Prisma Client being created, which consumes resources and might cause unexpected behavior. #### Recommended solution To avoid this, create a single Prisma Client instance by using a global variable: ```typescript // lib/prisma.ts import { PrismaClient } from "@prisma/client"; const globalForPrisma = global as unknown as { prisma: PrismaClient }; export const prisma = globalForPrisma.prisma || new PrismaClient(); if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; ``` Using this approach ensures that only one instance of Prisma Client exists, even during hot-reloading in development. --- ## Setting Up Prisma ORM in a Monorepo ### Challenges of using Prisma ORM in monorepos Monorepos allow multiple projects to share code and dependencies, making them a popular choice for modern development. However, using Prisma ORM in a monorepo can present challenges related to dependency resolution and schema management. #### Key issues 1. **Dependency Resolution**: Multiple packages in a monorepo might lead to conflicts if they use different version of Prisma ORM. 2. **Schema Centralization**: Managing a single Prisma Schema across multiple projects can be complex. #### Best practices for monorepo integration - **Centralize the Prisma Schema**: Place the `schema.prisma` file in a shared package, such as `@myorg/db`, to ensure consistency. - **Use a custom output directory for generated client**: Define a [custom output directory](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path) for the generated Prisma Client to maintain consistency across packages. - **Install dependencies in the root**: To prevent version conflicts, install Prisma ORM at the root of the monorepo. If individual packages need direct access to Prisma (e.g., for local client generation), install it within those packages as well. You can use a monorepo tool like Turborepo, following its [best practices](https://turbo.build/repo/docs/crafting-your-repository/managing-dependencies#keeping-dependencies-on-the-same-version), or adopt a similar strategy to keep dependencies synchronized across your app. - **Use NPM Scripts for Generation**: ```json { "scripts": { "prisma:generate": "prisma generate --schema=./packages/db/schema.prisma" } } ``` This approach keeps your Prisma Schema and generated client in sync across all projects in the monorepo. --- ## Dynamic usage of Prisma Client in Next.js ### Handling dynamic scenarios Dynamic use cases, such as working with tenant-specific databases, require additional consideration when using Prisma ORM with Next.js. #### Problem Each tenant might have its own database, necessitating the creation of separate Prisma Clients at runtime. This can be complex in Next.js due to its hybrid rendering model. #### Solution Use a factory function to dynamically create Prisma Clients based on tenant-specific configurations: ```typescript // lib/prismaDynamic.ts import { PrismaClient } from "@prisma/client"; type TenantConfig = { databaseUrl: string; }; export function createPrismaClient(config: TenantConfig): PrismaClient { return new PrismaClient({ datasources: { db: { url: config.databaseUrl, }, }, }); } ``` Ensure that you manage the lifecycle of dynamically created Prisma Clients to avoid resource exhaustion. --- # Solve package error with vercel/pkg URL: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/pkg-issue ## Problem If you use [vercel/pkg](https://github.com/vercel/pkg) to package your Node.js project, then you might encounter an `ENOENT` error like the following: ``` spawn /snapshot/enoent-problem/node_modules/.prisma/client/query-engine-debian-openssl-1.1.x ENOENT ``` ## Solution To avoid this error, add your Prisma query engine binary path to the `pkg/assets` section of your `package.json` file, as follows: ```json file=package.json copy { "pkg": { "assets": ["node_modules/.prisma/client/*.node"] } } ``` See [this Github issue](https://github.com/prisma/prisma/issues/8449) for further discussion. --- # Compare columns of the same table with raw queries URL: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/comparing-columns-through-raw-queries Comparing different columns from the same table is a common scenario that developers encounter. Some examples include comparing two numeric values in the same table or comparing two dates in a same table. There's an existing [GitHub Issue](https://github.com/prisma/prisma/issues/5048) regarding the same. :::warning From version 4.3.0, you do not need to use raw queries to compare columns in the same table. You can use the `.fields` property to [compare the columns](/orm/reference/prisma-client-reference#compare-columns-in-the-same-table). The below information is kept for backwards compatibility with Prisma ORM versions prior to 4.3.0. ::: ## Workaround Comparing values from two columns in the same table can be achieved by using [raw queries](/orm/prisma-client/using-raw-sql/raw-queries). ### Comparing numeric values From version 4.3.0, you do not need to use raw queries to compare columns in the same table. You can use the `.fields` property to compare the columns. [Learn more](/orm/reference/prisma-client-reference#compare-columns-in-the-same-table) One use case for comparing values from different columns would be retrieving posts that have more comments than likes; in this case, you need to compare the values of `commentsCount` and `likesCount`. ```prisma model Post { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int likesCount Int commentsCount Int } ``` Queries (depending upon which database) could look something like: _PostgreSQL / CockroachDB_ ```js import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function initiateNumbersComparisonRawQuery() { const response = await prisma.$queryRaw`SELECT * FROM "public"."Post" WHERE "likesCount" < "commentsCount";` console.log(response) } await initiateNumbersComparisonRawQuery() ``` _MySQL_ ```js import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function initiateNumbersComparisonRawQuery() { const response = await prisma.$queryRaw`SELECT * FROM \`public\`.\`Post\` WHERE \`likesCount\` < \`commentsCount\`;` console.log(response) } await initiateNumbersComparisonRawQuery() ``` _Sqlite_ ```js import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function initiateNumbersComparisonRawQuery() { const response = await prisma.$queryRaw`SELECT * FROM "Post" WHERE "likesCount" < "commentsCount";` console.log(response) } await initiateNumbersComparisonRawQuery() ``` Running the above queries (depending upon the database) would filter posts that has fewer likes compared to comments. _Query Response_ ```js ;[ { id: 1, createdAt: '2022-03-03T12:08:11.421+00:00', updatedAt: '2022-03-03T12:08:11.422+00:00', title: 'Hello World', content: 'This is my first post', published: false, authorId: 1, likesCount: 50, commentsCount: 100, }, ] ``` ### Comparing date values From version 4.3.0, you do not need to use raw queries to compare columns in the same table. You can use the `.fields` property to compare the columns. [Learn more](/orm/reference/prisma-client-reference#compare-columns-in-the-same-table) Similarly, if you need to compare dates, you could also achieve the same thing using raw queries. For example, a use case could be to get all projects completed after the due date. ```prisma model Project { id Int @id @default(autoincrement()) title String author User @relation(fields: [authorId], references: [id]) authorId Int dueDate DateTime completedDate DateTime createdAt DateTime @default(now()) } ``` Queries (depending upon the database) could look something like: _PostgreSQL / CockroachDB_ ```js import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function initiateDatesComparisonRawQuery() { const response = await prisma.$queryRaw`SELECT * FROM "public"."Project" WHERE "completedDate" > "dueDate";` console.log(response) } await initiateDatesComparisonRawQuery() ``` _MySQL_ ```js import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function initiateDatesComparisonRawQuery() { const response = await prisma.$queryRaw`SELECT * FROM \`public\`.\`Project\` WHERE \`completedDate\` > \`dueDate\`;` console.log(response) } await initiateDatesComparisonRawQuery() ``` _Sqlite_ ```js import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function initiateDatesComparisonRawQuery() { const response = await prisma.$queryRaw`SELECT * FROM "Project" WHERE "completedDate" > "dueDate";` console.log(response) } await initiateDatesComparisonRawQuery() ``` Running the above query would fetch projects where `completedDate` is after the `dueDate`. _Query Response_ ```js ;[ { id: 1, title: 'Project 1', authorId: 1, dueDate: '2022-03-10T00:00:00+00:00', completedDate: '2022-03-12T00:00:00+00:00', createdAt: '2022-03-03T12:08:11.421+00:00', }, ] ``` --- # Vercel build dependency caching workaround URL: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/vercel-caching-issue ## Problem If you deploy an application using Prisma ORM to [Vercel](https://vercel.com/), you may run into the following error message on deployment: ``` Prisma has detected that this project was built on Vercel, which caches dependencies. This leads to an outdated Prisma Client because Prisma's auto-generation isn't triggered. To fix this, make sure to run the `prisma generate` command during the build process. Learn how: https://pris.ly/d/vercel-build ``` This occurs because Vercel caches the dependencies of your project until one of those dependencies changes. It does this to allow faster builds, and while this is typically a good thing, it causes some problems for Prisma Client. Prisma ORM uses a `postinstall` hook to generate Prisma Client when dependencies are installed. Because Vercel uses cached modules, this `postinstall` hook never gets run in subsequent deployments after the initial deployment. This results in Prisma Client becoming out of sync with your database schema. This error message prevents this situation from happening and directs you here to learn how to fix the root issue.
Prisma Client versions below 4.13.0 On Prisma Client versions lower than 4.13.0, you may encounter error messages that look like the following: ``` // 1: When adding a field: Unknown arg `name` in data.name for type UserCreateInput. Did you mean `nick`? // 2: When removing a field: Invalid `prisma.user.create()` invocation: The column `User.name` does not exist in the current database. // 3: When a model was removed/renamed Invalid `prisma.user.deleteMany()` invocation: The table `public.User` does not exist in the current database. // 4: When a model was added Cannot read properties of undefined (reading 'create') ``` The solutions described in this guide are meant to solve these problems.
## Solution This issue can be solved by explicitly generating Prisma Client on every deployment. Running `prisma generate` before each deployment will ensure Prisma Client is up-to-date. You can configure the deployment to run this command in multiple different ways: ### A custom `postinstall` script This is the preferred method as it is a universal solution. Within the `scripts` section of your project's `package.json` file, if there is not already a script named `postinstall`, add one and add `prisma generate` to that script: ```json highlight=4;add { ... "scripts" { //add-next-line "postinstall": "prisma generate" } ... } ``` ### The application's `build` script in `package.json` Within the `scripts` section of your project's `package.json` file, within the `build` script, prepend `prisma generate` to the default `vercel build` command: ```json highlight=4;add { ... "scripts" { //add-next-line "build": "prisma generate && " } ... } ``` ### Vercel UI's build script field Another way to configure `prisma generate` to be run on every deployment is to add the command to the build settings via Vercel's UI. Within your project's dashboard, go to the **Settings** tab and find the **General** section. In that section you will find a box labeled **Build & Development Settings** that contains an input field named **Build Command**: ![Vercel project dashboard's Build Command setting](/img/orm/vercel-ui-build-command.png) Within that field, prepend `prisma generate` to the existing script: ![Vercel project dashboard's Build Command setting filled](/img/orm/vercel-ui-build-command-filled.png) --- # Netlify build dependency caching workaround URL: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/netlify-caching-issue ## Problem If you deploy an application using Prisma ORM to [Netlify](https://www.netlify.com/), you may run into the following error message on deployment: ``` Prisma has detected that this project was built on Netlify, which caches dependencies. This leads to an outdated Prisma Client because Prisma's auto-generation isn't triggered. To fix this, make sure to run the `prisma generate` command during the build process. Learn how: https://pris.ly/d/netlify-build ``` This occurs because Netlify caches the dependencies of your project until one of those dependencies changes. It does this to allow faster builds, and while this is typically a good thing, it causes some problems for Prisma Client. Prisma ORM uses a `postinstall` hook to generate Prisma Client when dependencies are installed. Because Netlify uses cached modules, this `postinstall` hook never gets run in subsequent deployments after the initial deployment. This results in Prisma Client becoming out of sync with your database schema. This error message prevents this situation from happening and directs you here to learn how to fix the root issue.
Prisma Client versions below 4.13.0 On Prisma Client versions lower than 4.13.0, you may encounter error messages that look like the following: ``` // 1: When adding a field: Unknown arg `name` in data.name for type UserCreateInput. Did you mean `nick`? // 2: When removing a field: Invalid `prisma.user.create()` invocation: The column `User.name` does not exist in the current database. // 3: When a model was removed/renamed Invalid `prisma.user.deleteMany()` invocation: The table `public.User` does not exist in the current database. // 4: When a model was added Cannot read properties of undefined (reading 'create') ``` The solutions described in this guide are meant to solve these problems.
## Solution This issue can be solved by explicitly generating Prisma Client on every deployment. Running `prisma generate` before each deployment will ensure Prisma Client is up-to-date. You can configure the deployment to run this command in multiple different ways: ### A custom `postinstall` script This is the preferred method as it is a universal solution. Within the `scripts` section of your project's `package.json` file, if there is not already a script named `postinstall`, add one and add prisma generate` in that script: ```json highlight=4;add { ... "scripts" { //add-next-line "postinstall": "prisma generate" } ... } ``` ### The application's `build` script in `package.json` Within the `scripts` section of your project's `package.json` file, within the `build` script, prepend `prisma generate` to the existing build command: ```json highlight=4;add { ... "scripts" { //add-next-line "build": "prisma generate && " } ... } ``` ### Netlify UI's build script field Another way to configure `prisma generate` to be run on every deployment is to add the command to the build settings via Netlify's UI. Within your project's dashboard, go to the **Site Settings** tab and find the **Build & deploy** section. In that section, enter the **Continuous deployment** subsection. Find the box in that section labeled **Build settings** and click the **Edit settings** button: ![Netlify project dashboard's Build settings button](/img/orm/netlify-edit-settings.png) Clicking that button will open a form with various fields. Find the **Build command** field and prepend `prisma generate` to the existing script: ![Netlify project dashboard's Build command setting filled](/img/orm/netlify-build-command-filled.png) --- # Data validation with CHECK constraints (PostgreSQL) URL: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/check-constraints ## Overview This page explains how to configure [check constraints](https://www.postgresql.org/docs/9.4/ddl-constraints.html#DDL-CONSTRAINTS-CHECK-CONSTRAINTS) in a PostgreSQL database. A check constraint is a condition that must be satisfied before a value can be saved to a table - for example, the discounted price of a product must always be less than the original price. Check constraints can be added when you create the table (using `CREATE TABLE`) or to a table that already exists (using `ALTER TABLE`). This guide covers all four combinations. At the end of the guide, you'll introspect your database, generate a Prisma Client, and write a simple Node.js script to validate the constraints. ## Prerequisites In order to follow this guide, you need: - a [PostgreSQL](https://www.postgresql.org/) database server running - the [`createdb`](https://www.postgresql.org/docs/9.1/app-createdb.html) command line utility - the [`psql`](https://www.postgresql.org/docs/13/app-psql.html) command line client for PostgreSQL - [Node.js](https://nodejs.org/) installed on your machine ## 1. Create a new database and project directory Start by creating a project directory for the files that you'll create throughout this guide. Open terminal or command line and run the following commands: ``` mkdir check-demo cd check-demo ``` Next, make sure that your PostgreSQL database server is running. Authenticate the default `postgres` user: Unix (bash): ``` sudo -u postgres ``` Windows (command line): ``` psql -U postgres ``` Then execute the following command in your terminal to create a new database called `CheckDemo`: Unix (bash): ``` createdb CheckDemo ``` Windows (command line): ``` create database CheckDemo; //delete-next-line \connect CheckDemo ``` > _Tip_: Remember the trailing `;`! `postgres=#` `postgres-#` You can validate that the database was created by running the `\dt` command which lists all tables (_relations_) in your database (right now there are none): Unix (bash): ``` psql -d CheckDemo -c "\dt" ``` Windows (command line): ``` -d CheckDemo -c \dt ``` ## 2. Adding a table with a single check constraint on a single column In this section, you'll **create a new table with a single check constraint on a single column** in the `CheckDemo` database. Create a new file named `single-column-check-constraint.sql` and add the following code to it: ```sql CREATE TABLE "public"."product" ( price NUMERIC CONSTRAINT price_value_check CHECK (price > 0.01 AND price <> 1240.00) ); ALTER TABLE "public"."product" ADD COLUMN "productid" serial, ADD PRIMARY KEY ("productid"); ``` Now run the SQL statement against your database to create a new table called `product`: Unix (bash): ``` psql CheckDemo < single-column-check-constraint.sql ``` Windows (command line): ``` \i 'c:/checkdemo/single-column-check-constraint.sql' ``` Congratulations, you just created a table called `product` in the database. The table has one column called `price`, which has a single check constraint that ensures price of a product is: - Never less than 0.01 - Never equal to 1240.00 Run the following command to see the a list of check constraints that apply to the `product` table: ``` \d+ product ``` You will see the following output, which includes a list of all check constraints: ``` Table "public.product" Column | Type | Collation | Nullable | Default | Storage | Stats target | Description --------+---------+-----------+----------+---------+---------+--------------+------------- price | numeric | | | | main | | Check constraints: "price_value_check" CHECK (price > 0.01 AND price <> 1240.00) ``` Note that PostgreSQL will auto-generate a constraint name if you do not provide one. For example, the constraint created by `price NUMERIC CHECK (price > 0.01 AND price <> 1240.00)` would be `price_check`. ## 3. Adding a table with a multi-column check constraint Next, you'll **create a table with a multi-column check constraint** that compares the values of two columns. Create a new file named `multi-column-check-constraint.sql` and add the following code to it: ```sql CREATE TABLE "public"."anotherproduct" ( reducedprice NUMERIC CONSTRAINT reduced_price_check CHECK (price > reducedprice), price NUMERIC ); ALTER TABLE "public"."anotherproduct" ADD COLUMN "productid" serial, ADD PRIMARY KEY ("productid"); ``` Now run the SQL statement against your database to create a new table called `anotherproduct`: Unix (bash): ``` psql CheckDemo < multi-column-check-constraint.sql ``` Windows (command line): ``` \i 'c:/checkdemo/multi-column-check-constraint.sql' ``` Congratulations, you just created a table called `anotherproduct` in the database. The table has two columns called `reducedprice` and `price`. The `reducedprice` column has a check constraint that ensures that the value of `reducedprice` is always less than the value of `price`. ## 4. Adding a table with multiple check constraints Next, you'll **create a table with multiple check constraint** on different columns. Create a new file named `multiple-check-constraints.sql` and add the following code to it: ```sql CREATE TABLE "public"."secondtolastproduct" ( reducedprice NUMERIC CONSTRAINT reduced_price_check CHECK (price > reducedprice), price NUMERIC, tags TEXT[] CONSTRAINT tags_contains_product CHECK ('product' = ANY(tags)) ); ALTER TABLE "public"."secondtolastproduct" ADD COLUMN "productid" serial, ADD PRIMARY KEY ("productid"); ``` Now run the SQL statement against your database to create a new table called `secondtolastproduct`: Unix (bash): ``` psql CheckDemo < multiple-check-constraints.sql ``` Windows (command line): ``` \i 'c:/checkdemo/multiple-check-constraints.sql' ``` Congratulations, you just created a table called `lastproduct` in the database. The table has three columns named `reducedprice`, `price` and `tags`, and the following check constraints: - The `tags` column (which is an array) must contain a tag named `product` - The value of `reducedprice` must be less than the value of `price` ## 5. Adding a check constraint to an existing table In this section, you'll **add a check constraint to a table that already exists in your database**. To do so, you first need to create a new table and then alter the table to add the constraint. Create a new file named `add-single-check-constraint-later.sql` and add the following code: ```sql CREATE TABLE "public"."lastproduct" ( category TEXT ); ALTER TABLE "public"."lastproduct" ADD CONSTRAINT "category_not_clothing" CHECK (category <> 'clothing'); ``` This code contains two SQL statements: 1. Create a new table called `lastproduct` 2. Alter the table to add a check constraint named `price_not_zero_constraint` Now run the SQL statements against your database to create a new table called `lastproduct`: Unix (bash): ``` psql CheckDemo < add-single-check-constraint-later.sql ``` Windows (command line): ``` \i 'c:/checkdemo/add-single-check-constraint-later.sql' ``` Congratulations, you just created a table called `lastproduct` in the database with a single column called `price`. You added constraint named `price_not_zero_constraint` to with a second SQL command, which ensures that the price of a product is never less than 0.01. ## 6. Introspect your database with Prisma ORM In the previous sections, you created four tables with different check constraints: - The `product` table has a check constraint that ensures that the value of `price` is never less than `0.01` and never exactly `1240.00`. - The `anotherproduct` table has a check constraint that ensures that the value of `reducedprice` is never greater than the value of `price`. - The `secondtolastproduct` table has two check constraints - one that ensures that the value of `reducedprice` is never greater than the value of `price`, and one that ensures that the `tags` array always contains the value `product`. - The `lastproduct` table has a check constraint that ensures that the value of `category` is never `clothing`. In this section you'll introspect your database to generate the Prisma models for these tables. > **Note**: Check constraints are currently not included in the generated Prisma schema - however, the underlying database still enforces the constraints. To start, set up a new Node.js project and add the `prisma` CLI as a development dependency: ``` npm init -y npm install prisma --save-dev ``` In order to introspect your database, you need to tell Prisma ORM how to connect to it. You do so by configuring a `datasource` in your Prisma schema. Create a new file named `schema.prisma` and add the following code to it: ```prisma file=schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` The database connection URL is set via an environment variable. The Prisma CLI automatically supports the [`dotenv`](https://github.com/motdotla/dotenv) format which automatically picks up environment variables defined in a file named `.env`. Create a new file named `.env` and set your database connection URL as the `DATABASE_URL` environment variable: ``` DATABASE_URL=postgresql://__USER__:__PASSWORD__@__HOST__:__PORT__/CheckDemo ``` In the above code snippet, you need to replace the uppercase placeholders with your own connection details. For example, if your database is running locally it could look like this: ``` DATABASE_URL=postgresql://janedoe:mypassword@localhost:5432/CheckDemo ``` With both the `schema.prisma` and `.env` files in place, you can run Prisma ORM's introspection with the following command: ``` npx prisma db pull ``` This command introspects your database and for each table adds a Prisma model to the Prisma schema: ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model anotherproduct { price Float? productid Int @id reducedprice Float? } model lastproduct { category String? productid Int @id } model product { price Float? productid Int @id } model secondtolastproduct { price Float? productid Int @id reducedprice Float? tags String[] } ``` ## 7. Generate Prisma Client To validate whether the check constraints work, you'll now generate Prisma Client and send a few sample queries to the database. First, add a `generator` block to your Prisma schema (typically added right below the `datasource` block): ```prisma file=schema.prisma showLineNumbers generator client { provider = "prisma-client-js" } ``` Run the following command to install and generate Prisma Client in your project: ``` npx prisma generate ``` Now you can use Prisma Client to send database queries in Node.js. ## 8. Validate the check constraints in a Node.js script Create a new file named `index.js` and add the following code to it: ```js const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { const newProduct = await prisma.product.create({ data: { price: 0.0, }, }) console.log(newProduct) } main() ``` In this code, you're creating a product with a price of `0.00`, which does not meet the check constraint configured for the `price` column. Run the code with this command: ``` node index.js ``` The script throws an error indicating that the `price_check_value` check constraint was not met: ``` Error occurred during query execution: ConnectorError(ConnectorError { user_facing_error: None, kind: QueryError(Error { kind: Db, cause: Some(DbError { severity: "ERROR", parsed_severity: Some(Error), code: SqlState("23514"), message: "new row for relation \"product\" violates check constraint \"price_value_check\"", detail: Some("Failing row contains (0, 11)."), hint: None, position: None, where_: None, schema: Some("public"), table: Some("product"), column: None, datatype: None, constraint: Some("price_value_check"), file: Some("d:\\pginstaller_12.auto\\postgres.windows-x64\\src\\backend\\executor\\execmain.c"), line: Some(2023), routine: Some("ExecConstraints") }) }) }) ``` To validate the multi-column check constraint, replace the code in `index.js` with the following: ```js const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { const newProduct = await prisma.anotherproduct.create({ data: { price: 50.0, reducedprice: 100.0, }, }) console.log(newProduct) } main() ``` In this code, you're creating a product where the reduced price is higher than the actual price. Run the script again with this command: ``` node index.js ``` This time, you'll see a similar error message indicating the `reduce_price_check` check constraint was not met: ``` ConnectorError(ConnectorError { user_facing_error: None, kind: QueryError(Error { kind: Db, cause: Some(DbError { severity: "ERROR", parsed_severity: Some(Error), code: SqlState("23514"), message: "new row for relation \"anotherproduct\" violates check constraint \"reduced_price_check\"", detail: Some("Failing row contains (100, 50, 1)."), hint: None, position: None, where_: None, schema: Some("public"), table: Some("anotherproduct"), column: None, datatype: None, constraint: Some("reduced_price_check"), file: Some("d:\\pginstaller_12.auto\\postgres.windows-x64\\src\\backend\\executor\\execmain.c"), line: Some(2023), routine: Some("ExecConstraints") }) }) }) at PrismaClientFetcher.request (C:\Work\Personal\prisma-check-constraint\node_modules\@prisma\client\index.js:89:17) ``` Finally, modify the script to include multiple check constraint violations: ```js const { PrismaClient } = require('@prisma/client') const prisma = new PrismaClient() async function main() { const newProduct = await prisma.secondtolastproduct.create({ data: { tags: { set: ['wrongtag'], }, price: 90.0, reducedprice: 100.0, }, }) console.log(newProduct) } main() ``` In this code, you're creating a product where the reduced price is higher than the actual price, and omitting the required `product` tag. Run the script again with this command: ``` node index.js ``` Notice that the error message only mentions the `reduced_price_check` constraint: ``` ConnectorError(ConnectorError { user_facing_error: None, kind: QueryError(Error { kind: Db, cause: Some(DbError { severity: "ERROR", parsed_severity: Some(Error), code: SqlState("23514"), message: "new row for relation \"secondtolastproduct\" violates check constraint \"reduced_price_check\"", detail: Some("Failing row contains (100, 90, {wrongtag}, 7)."), hint: None, position: None, where_: None, schema: Some("public"), table: Some("secondtolastproduct"), column: None, datatype: None, constraint: Some("reduced_price_check"), file: Some("d:\\pginstaller_12.auto\\postgres.windows-x64\\src\\backend\\executor\\execmain.c"), line: Some(2023), routine: Some("ExecConstraints") }) }) }) ``` Check constraints are resolved in alphabetical order, and only the first constraint to fail appears in the error message. --- # Using the Nuxt Prisma Module URL: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/prisma-nuxt-module The Nuxt Prisma module simplifies the integration of Prisma ORM into your Nuxt applications. [Prisma ORM](/orm/overview/introduction/what-is-prisma) is a database library that lets you model your database schema, provides auto-generated migrations and lets you query the database in an intuitive and type-safe way. This module provides several features to streamline the setup and usage of Prisma ORM in a Nuxt application, making it easier to interact with your database. ## Features - **Project initialization**: Automatically sets up a Prisma ORM project with a SQLite database within your Nuxt project. - **Composable**: Provides an auto-imported `usePrismaClient()` composable for use in your Vue files. - **API route integration**: Automatically imports an instance of `PrismaClient` for use in API routes to query your DB. - **Prisma Studio access**: Enables access to Prisma Studio through Nuxt Devtools for viewing and manually editing data. ## Getting started 1. Create a [new Nuxt Project](https://nuxt.com/docs/getting-started/installation#new-project): ```terminal npm create nuxt test-nuxt-app ``` 2. Navigate to project directory and install `@prisma/nuxt` using the Nuxt CLI: ```terminal cd test-nuxt-app npx nuxi@latest module add @prisma/nuxt ```
:::warning If you're using `pnpm`, make sure to hoist Prisma dependencies. Follow the [Prisma studio steps](#prisma-studio-not-opening-with-pnpm) for detailed instructions. ::: 3. Start the development server: ```terminal npm run dev ``` Starting the development server will: 1. Automatically install the [Prisma CLI](/orm/reference/prisma-cli-reference) 2. Initialize a Prisma project with SQLite 3. Create an `User` and `Post` example model in the Prisma Schema file: ```prisma file=prisma/schema.prisma // This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } datasource db { provider = "sqlite" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int } ``` 4. Prompt you to run a migration to create database tables with [Prisma Migrate](/orm/prisma-migrate/understanding-prisma-migrate/overview) The database migrates automatically the first time you start the module if there isn't a `migrations` folder. After that, you need to run `npx prisma migrate dev` manually in the CLI to apply any schema changes. Running the `npx prisma migrate dev` command manually makes it easier and safer to manage migrations and also to [troubleshoot](/orm/prisma-migrate/workflows/troubleshooting) any migration-related errors. 5. Install and generate a [Prisma Client](/orm/reference/prisma-client-reference) which enables you to query your DB 6. Automatically start [Prisma Studio](/orm/tools/prisma-studio) 4. You can now use Prisma ORM in your project. If you accepted the prompt to add Prisma Studio, you can access Prisma Studio through the Nuxt Devtools. See the [usage section](#usage) to learn how to use Prisma Client in your app. ## Using a different database provider The `@prisma/nuxt` module works with any [database provider that Prisma ORM supports](/orm/reference/supported-databases). You can configure the [getting started example](#getting-started) to use a database of your choice. The steps would be different for a [database without existing data](#using-a-database-without-existing-data) and a [database with pre-existing data](#using-a-database-with-pre-existing-data). ### Using a database without existing data To configure [the getting started example](#getting-started) to use a PostgreSQL database without any existing data: 1. Stop the Nuxt development server and Prisma Studio (if they are still running): ```terminal npx kill-port 3000 # Stops Nuxt dev server (default port) npx kill-port 5555 # Stops Prisma Studio (default port) ``` 2. Navigate to the `schema.prisma` file and update the `datasource` block to specify the `postgresql` provider: ```prisma file=prisma/schema.prisma // This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int } ``` 2. Update the `DATABASE_URL` environment variable in the `.env` file with your PostgreSQL database URL: ```.env file=.env ## This is a sample database URL, please use a valid URL DATABASE_URL="postgresql://janedoe:mypassword@localhost:5432/mydb?schema=sample" ``` 3. Delete the SQLite database file and the migrations folder: ```terminal rm prisma/dev.db # Delete SQLite database file rm -r prisma/migrations # Delete the pre-existing migrations folder ``` 4. Run the development server: ```terminal npm run dev ``` Starting the development server will prompt you to migrate the schema changes to the database, to which you should agree. Then agree to the prompt to install and access Prisma Studio from the Nuxt Devtools. 5. The `@prisma/nuxt` module is ready to use with your PostgreSQL database. See the [usage section](#usage) to learn how to use Prisma Client in your app. ### Using a database with pre-existing data To configure [the getting started example](#getting-started) to use a PostgreSQL database that already has data in it: 1. Stop the dev server and Prisma Studio (if they are still running): ```terminal // stops Nuxt dev server from running incase it's still running npx kill-port 3000 // stops Prisma Studio instance incase it's still running npx kill-port 5555 ``` 2. Delete the Prisma folder: ```terminal rm -r prisma/ ``` 3. Update the `DATABASE_URL` environment variable in the `.env` file with your PostgreSQL database URL: ```.env file=.env ## This is a sample database URL, please use a valid URL DATABASE_URL="postgresql://janedoe:mypassword@localhost:5432/mydb?schema=sample" ``` 4. To generate a Prisma Schema and migrations folder from the existing database, you have to [introspect](/orm/prisma-schema/introspection) the database. Complete **step 1** to **step 4** from the [introspection guide](/orm/prisma-migrate/getting-started#adding-prisma-migrate-to-an-existing-project) and continue. 5. Starting the development server will skip the prompt to migrate the schema changes to the database, as the migrations folder already exists. Agree to the prompt to install and access Prisma Studio from the Nuxt Devtools. 6. The `@prisma/nuxt` module is ready to be used with your PostgreSQL database. See the [usage section](#usage) to learn how to use Prisma Client in your app. ## Usage ### Option A: `usePrismaClient` composable #### Using the composable in your Nuxt server component If you're using [Nuxt server components](https://nuxt.com/docs/guide/directory-structure/components#server-components), you can use the global instance of the Prisma Client in your `.server.vue` files: ```html ``` ### Option B: `lib/prisma.ts` After running through the initial setup prompts, this module creates the `lib/prisma.ts` file which contains a global instance of Prisma Client. ```typescript file=lib/prisma.ts import { PrismaClient } from '@prisma/client' const prismaClientSingleton = () => { return new PrismaClient() } declare const globalThis: { prismaGlobal: ReturnType; } & typeof global; const prisma = globalThis.prismaGlobal ?? prismaClientSingleton() export default prisma if (process.env.NODE_ENV !== 'production') globalThis.prismaGlobal = prisma ``` You can customize Prisma Client's capabilities by using client extensions in your `lib/prisma.ts` file. Here is an example using the [Accelerate client extension](https://www.npmjs.com/package/@prisma/extension-accelerate): ```typescript file=lib/prisma.ts import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' const prismaClientSingleton = () => { return new PrismaClient().$extends(withAccelerate()) } declare const globalThis: { prismaGlobal: ReturnType; } & typeof global; const prisma = globalThis.prismaGlobal ?? prismaClientSingleton() export default prisma if (process.env.NODE_ENV !== 'production') globalThis.prismaGlobal = prisma ```
:::info Use the `prisma` instance from the `lib` folder if you want to leverage a client using [Prisma Client extensions](/orm/prisma-client/client-extensions). ::: #### Using the global Prisma Client instance in your API route You can use the global instance of the Prisma Client in your Nuxt API route as follows: ```typescript import prisma from "~/lib/prisma"; export default defineEventHandler(async (event) => { return { user: await prisma.user.findFirst(), }; }); ``` #### Using the global Prisma Client instance in your Nuxt server component If you're using [Nuxt server components](https://nuxt.com/docs/guide/directory-structure/components#server-components), you can use the global instance of the Prisma Client `.server.vue` files: ```html ``` ## Configuration You can configure the `@prisma/nuxt` module by using the `prisma` key in `nuxt.config.ts`: ```ts file=nuxt.config.ts export default defineNuxtConfig({ // ... prisma: { // Options } }) ```
The `prisma` key is available in `nuxt.config.ts` after successfully setting up the module by running `npm run dev` | Option | Type | Default | Description | |---------------------|-----------|---------|-------------| | **installCLI** | `boolean` | true | Whether to install the [Prisma CLI](/orm/tools/prisma-cli). | | **installClient** | `boolean` | true | Whether to install the [Prisma Client](/orm/prisma-client) library in the project. | | **generateClient** | `boolean` | true | Whether to [generate](/orm/prisma-client/setup-and-configuration/generating-prisma-client) the `PrismaClient` instance. Executes `npx prisma generate` on every run to update the client based on the schema changes. | | **formatSchema** | `boolean` | true | Whether to [format](/orm/reference/prisma-cli-reference#format) the [Prisma Schema](/orm/prisma-schema) file. | | **installStudio** | `boolean` | true | Whether to install and start [Prisma Studio](https://www.prisma.io/studio) in the Nuxt Devtools. | | **autoSetupPrisma** | `boolean` | false | Whether to skip all prompts during setup. This option is useful for automating Prisma setup in scripts or CI/CD pipelines. | | **skipPrompts** | `false` | false | Skips all prompts | | **prismaRoot** | `string` | false | Required when using [Nuxt layers](https://nuxt.com/docs/getting-started/layers). For example, if you have a Nuxt layer called `database`, the `prismaRoot` would be `./database` in the base nuxt config. This refers to the folder where Prisma will be initialized or checked. | | **prismaSchemaPath** | `string` | `undefined` | Required when using [Nuxt layers](https://nuxt.com/docs/getting-started/layers). For example, if you have a Nuxt layer called `database`, the `prismaSchemaPath` would be `./database/prisma/schema.prisma` in the base nuxt config. | | **runMigration** | `boolean` | true | Whether to run a Prisma Migration automatically. If you are using MongoDB or PlanetScale, use the [`npx prisma db push` command](/orm/prisma-migrate/workflows/prototyping-your-schema#choosing-db-push-or-prisma-migrate). Migrations aren’t supported for these databases, so this command will ensure your schema is updated appropriately. | ## Limitations ### `PrismaClient` constructor options are not configurable in the `usePrismaClient` composable The `usePrismaClient` module does not currently allow for configuration of `PrismaClient` [constructor options](/orm/reference/prisma-client-reference#prismaclient). ### The `usePrismaClient` composable is not supported in edge runtimes The `usePrismaClient` composable currently relies on a `PrismaClient` instance that does not work in edge runtimes. If you require edge support for the composable, please let us know on [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=inline_text) or [GitHub](https://github.com/prisma/nuxt-prisma). ## Troubleshooting ### Prisma Studio not opening with `pnpm` If you're encountering the following error when using `pnpm` and Prisma Studio isn't opening: ```terminal Uncaught SyntaxError: The requested module '/_nuxt/node_modules/.pnpm/*@*/node_modules/@prisma/client/index-browser.js?v=' does not provide an export named 'PrismaClient' (at plugin.mjs?v=*) ``` To resolve this issue, create a `.npmrc` file in your project root and add the following configuration to hoist Prisma dependencies: ```.npmrc file=.npmrc hoist-pattern[]=*prisma* ``` This will ensure that Prisma dependencies are properly resolved by `pnpm`. ### Resolving `TypeError: Failed to resolve module specifier ".prisma/client/index-browser"` If you encounter the following error message in the browser console after building and previewing your application: ``` TypeError: Failed to resolve module specifier ".prisma/client/index-browser" ``` To resolve this issue, add the following configuration to your nuxt.config.ts file: ```ts file=nuxt.config.ts import { defineNuxtConfig } from 'nuxt' export default defineNuxtConfig({ modules: [ '@prisma/nuxt', ], // additional config vite: { resolve: { alias: { '.prisma/client/index-browser': './node_modules/.prisma/client/index-browser.js', }, }, }, }) ``` This configuration ensures that the module specifier is correctly mapped to the appropriate file. ### Limitations in package manager support The module is designed to work with popular package managers, including npm, Yarn, and pnpm. However, as of `v0.2`, it is not fully compatible with Bun due to an issue causing an indefinite installation loop. Additionally, this package has not been tested with Deno and is therefore not officially **supported.** --- # Help articles URL: https://www.prisma.io/docs/orm/more/help-and-troubleshooting/index This section provides a number of common problems that developers might encounter when using Prisma ORM and provides short, practical solutions to resolve them. ## Help articles --- # ORM releases and maturity levels URL: https://www.prisma.io/docs/orm/more/releases This page explains the release process of Prisma ORM, how it's versioned and how to deal with breaking changes that might happen throughout releases. ## Releases Prisma ORM releases typically happen every three weeks. Note that this is _not_ a hard rule – releases might be postponed for internal reasons. [Check out all the releases notes in GitHub](https://github.com/prisma/prisma/releases). ## Product maturity levels A release can include products or features at different maturity levels. Maturity level describes a product or feature's completeness and what users can expect in terms of breaking changes. > **Note**: As of version [2.13.0](https://github.com/prisma/prisma/releases/2.13.0), 'Experimental' is no longer part of the product maturity scale. ### Early Access If a feature or product is **Early Access**: - We have validated a problem and are considering a solution to it but are not certain whether that solution is complete or a perfect fit. - We want to gather more feedback and adjust the solution as necessary, knowing that users are prepared for significant breaking changes We don't recommend using Early Access features or products in production. ### Preview If a feature or product is a **Preview**: - We have validated the feature or product in terms of direction and surface. - Users can count on the feature or product and associated API to be mostly stable unless stated otherwise in the release notes and documentation. - There are no significant known issues, although minor bugs may exist. - We welcome feedback on these to make the solution stable as quickly as possible. Previews are typically available behind a feature flag or require some form of opt-in (for example, by providing a `--preview-feature` flag in the CLI or [adding them to a `previewFeatures` property in the `generator` block](/orm/reference/preview-features/cli-preview-features) for Prisma Client in your Prisma schema). We don't recommend using Preview features or products in production. See also: [All currently available Preview features](/orm/reference/preview-features). ### Generally Available (GA) If a feature or product is **Generally Available**: - The solution has been tested for some time and we received enough feedback to consider it stable and ready for production use. - There should be no bugs in 99% of cases (completely bug-free software cannot be guaranteed) ## Versioning Prisma ORM's release scheme adheres to Semantic Versioning ([SemVer](https://semver.org/)) starting with version `3.x.x`. ### Prisma ORM and Semantic Versioning (SemVer) #### How does SemVer versioning work? Semantic Versioning (SemVer) uses the following rules for version upgrade (quoted from the [SemVer](https://semver.org/) spec): _Given a version number `MAJOR.MINOR.PATCH`, increment the:_ 1. _`MAJOR` version when you make incompatible API changes,_ 1. _`MINOR` version when you add functionality in a backward compatible manner, and_ 1. _`PATCH` version when you make backward compatible bug fixes._ #### How does Prisma ORM versioning follow SemVer? Beginning with version `3.x.x`, Prisma ORM adheres strictly to the [SemVer](https://semver.org/) versioning scheme. Here is a brief overview of how Prisma ORM's follows SemVer: - Breaking changes in stable surface (i.e. [General Availability](#generally-available-ga)) will only be introduced in new `MAJOR` releases. - Breaking changes can still be rolled out in `MINOR` but only for opt-in Preview and Early Access features that are not active by default (e.g. via a Preview feature flag or a specific opt-in option or new CLI command). - Opt-in breaking changes, i.e. Preview and Early Access, released in `MINOR`, will only be promoted to General Availability (no requirement for opt-in) in new `MAJOR` releases. Given a version number `MAJOR.MINOR.PATCH`, Prisma ORM's version number is incremented as follows: 1. `MAJOR` version is incremented when major product updates **with breaking changes** are released to General Availability. 1. `MINOR` version is incremented when product updates adding backward compatible new functionality are released. Features with breaking changes may only be introduced if they are **opt-in**, i.e. Early Access and Preview. 1. `PATCH` version is incremented when functionality bugs are fixed and are always **backward compatible**. > **Note:** Up until version `2.28.0`, Prisma ORM did not follow SemVer versioning strictly. This means that releases in the `2.MINOR.PATCH` range, `MINOR` versions may have included breaking changes. To learn more about Prisma ORM's adoption of SemVer, check out the [blog post](https://www.prisma.io/blog/prisma-adopts-semver-strictly). --- # More URL: https://www.prisma.io/docs/orm/more/index ## In this section --- # ORM URL: https://www.prisma.io/docs/orm/index [Prisma ORM](https://github.com/prisma/prisma) is a Node.js and TypeScript ORM with an intuitive data model, automated migrations, type-safety, and auto-completion. ## In this section --- # FAQ URL: https://www.prisma.io/docs/postgres/faq ## Does query execution time affect pricing in Prisma Postgres? No, cost for Prisma Postgres is based solely on the _number of operations_ (i.e. Prisma ORM queries), not the amount of compute required to execute them. Whether a query takes 10ms or 10sec to execute, its pricing impact remains the same. ## Do read and write queries cost the same? Yes, read and write queries are counted equally as _operations_ and are billed the same way. ## Does a `SELECT 1` query count as a billable operation? Yes, if submitted via Prisma ORM, a query like `SELECT 1` counts as an operation and will be billed accordingly (even if no actual data is accessed in the query). ## Can I use Prisma Postgres without Prisma ORM? Prisma Postgres is designed to be used with Prisma ORM and the Accelerate extension for best performance and scalability. While it is technically possible to connect via the [TCP tunnel](/postgres/tcp-tunnel), this approach is only intended for _tooling_ purposes, such as command line tools or query editors. :::warning We strongly advise against using the TCP tunnel for application-level access. It is not designed for that purpose and using it that way will likely have negative performance implications for your application. ::: We are planning to enable application-level TCP access in the future so that you can use Prisma Postgres with other ORMs. --- # Netlify URL: https://www.prisma.io/docs/postgres/integrations/netlify ## Overview The [Netlify extension for Prisma Postgres](https://www.netlify.com/integrations/prisma) connects your Netlify sites with Prisma Postgres instances. Once connected, the extension will automatically set the `DATABASE_URL` environment variable on your deployed Netlify sites. ## Features - Automatic generation of Prisma Postgres API keys for production and preview environments. - Simplified environment configuration for your Netlify site. ## Usage ### Install the extension To install the extension, click **Install** at the top of the [Prisma Postgres extension page](https://www.netlify.com/integrations/prisma). ### Add the Prisma Platform integration token to your Netlify team Perform the following steps _once_ to connect your Netlify team with a Prisma Platform workspace: 1. Log in to your [Prisma Console](https://console.prisma.io). 2. Select the workspace you want to connect to Netlify. 3. Navigate to the **Integrations** menu in the left-hand sidebar. 4. Follow the prompts to create a new Netlify integration token and copy the token value. 5. Paste the token into the **Integration Token** field above. The workspace ID will be automatically filled in. 6. Click **Save** to complete the setup. Once this setup is complete, your Netlify team is connected to your Prisma workspace. You can now configure individual Netlify sites to use Prisma Postgres. ### Add Prisma Postgres to a Netlify site Perform the following steps _for every Netlify site_ in which you want to use Prisma Postgres: 1. Go to the site view in Netlify and click **Prisma Postgres** under the **Extensions** section. 2. From the **Project** selector, choose the Prisma project you want to connect to your Netlify site. 3. Configure the environment for your **Production environment**. 4. Configure the environment for your **Preview environment**. 5. Click **Save** to complete the site setup. 6. The extension will automatically create a Prisma Postgres instance and store its connection URL in the `DATABASE_URL` environment variable. ## Additional considerations ### Ensure your project uses the `DATABASE_URL` environment variable Ensure that the data source in your `schema.prisma` file is configured to use the `DATABASE_URL` environment variable: ```prisma // schema.prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` ### Generate Prisma Client in a `postinstall` script in `package.json` To ensure the generated Prisma Client library is available on your deployed Netlify site, you should add a `postinstall` script to the `scripts` section of your `package.json` file: ```js file=package.json { // ... "scripts": { // ... // add-next-line "postinstall": "prisma generate --no-engine" } // } ``` The `--no-engine` flag ensures that the query engine binary is kept out of the generated Prisma Client library. It's not needed when using Prisma Postgres. ## Example: Deploy a Next.js template with Prisma Postgres This section contains step-by-step instructions for deploying a Netlify site and connecting it to Prisma Postgres from scratch using Netlify's official [Next.js Platform Starter](https://github.com/netlify-templates/next-platform-starter) template. ### 1. Create a new site using the template In your Netlify team, create a new site using the template: 1. Select **Sites** in the left sidenav. 1. Click the **Add new site** button. 1. In the dropdown, select **Start from a template**. 1. Select the **Next.js Platform Starter**. 1. Follow the prompts to **Clone this template to your Git provider**. 1. Enter a **Site name** and click the **Deploy site** button. Once you're done with this, you'll be able to access the deployed version of this starter project. ### 2. Set up a Prisma Postgres instance Next, set up a Prisma Postgres instance: 1. Log in to [Prisma Data Platform](https://console.prisma.io/) and open the Console. 1. In a [workspace](/platform/about#workspace) of your choice, click the **New project** button. 1. Type a name for your project in the **Name** field, e.g. **hello-ppg**. 1. In the **Prisma Postgres** section, click the **Get started** button. 1. In the **Region** dropdown, select the region that's closest to your current location, e.g. **US East (N. Virginia)**. 1. Click the **Create project** button. 1. Save the `DATABASE_URL` environment variable, you'll need it in the next section. ### 3. Locally add Prisma Postgres to the project In this section, you are going to add Prisma Postgres to the starter project _on your local machine_: #### 3.1. Set up Prisma ORM 1. Clone the Next.js Platform Starter repo that was added to your GitHub account in step 1. 1. Navigate into the project directory, e.g.: `cd next-platform-starter`. 1. Install the Prisma CLI as a development dependency: ```terminal npm install prisma --save-dev ``` 1. Initialize Prisma ORM to create Prisma schema and `.env` file: ```terminal npx prisma init ``` #### 3.2. Run migration and create sample data 1. Open the newly created `schema.prisma` file and add the following model to it: ```prisma file=schema.prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } // add-start model User { id Int @id @default(autoincrement()) name String? email String @unique } // add-end ``` 1. Open the newly created `.env` file and paste the `DATABASE_URL` environment variable from the previous section into it. 1. Run your first migration to map the `User` model to the database: ```terminal npx prisma migrate dev --name init ``` 1. Create (at least) one `User` record in the database with Prisma Studio: ```terminal npx prisma studio ``` #### 3.3. Update application code to query and show `User` records Open the `app/page.jsx` file and replace the entire contents with this code: ```js file=app/page.jsx import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient(); export default async function Page() { const users = await prisma.user.findMany(); return (

Users

    {users.length > 0 ? ( users.map(user => (
  • ID: {user.id}

    Name: {user.name || 'N/A'}

    Email: {user.email}

  • )) ) : (

    No users found.

    )}
); } ``` With this code in place, you can now go ahead and run the app locally: ```terminal npm run dev ``` You should see a list of the `User` records that you created in the previous step. #### 3.4. Add the `postinstall` script to generate Prisma Client As mentioned [above](#generate-prisma-client-in-a-postinstall-script-in-packagejson), you need to add a `postinstall` script to your `package.json` to ensure your Prisma Client library gets properly generated: ```json file=package.json { "name": "next-netlify-platform-starter", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev", "build": "next build", "start": "next start", "lint": "next lint", // add-next-line "postinstall": "prisma generate --no-engine" }, "dependencies": { "@netlify/blobs": "^8.1.0", "@prisma/client": "^6.3.0", "@prisma/extension-accelerate": "^1.2.1", "blobshape": "^1.0.0", "bright": "^0.8.5", "markdown-to-jsx": "^7.4.5", "next": "15.1.6", "react": "18.3.1", "react-dom": "18.3.1", "unique-names-generator": "^4.7.1" }, "devDependencies": { "autoprefixer": "^10.4.18", "daisyui": "^4.12.8", "eslint": "8.57.1", "eslint-config-next": "15.1.6", "postcss": "^8.4.36", "prisma": "^6.3.0", "tailwindcss": "^3.4.1" } } ``` ### 4. Configure the Netlify extension for Prisma Postgres In this section, you need to add the Netlify extension to your Netlify site. Follow the instructions in the [Usage](#usage) section above to do that. After having completed these steps, find the **Trigger deploy** button and select **Clear cache and deploy site** in the dropdown. ### 5. Validate the deployment Open the deployed site by clicking the **Open production deploy** button. You should now see the same UI as you did at the end of step 3 when you were running the app locally. --- # Vercel URL: https://www.prisma.io/docs/postgres/integrations/vercel The [Vercel Marketplace integration for Prisma Postgres](https://www.vercel.com/marketplace/prisma) connects your Vercel projects with Prisma Postgres instances. Once connected, the integration will automatically set the `DATABASE_URL` environment variable on your deployed Vercel app. ## Features - Create and use Prisma Postgres instances without leaving the Vercel dashboard. - Automatic generation of Prisma Postgres URLs keys for production and preview environments. - Simplified environment configuration for your Vercel project. - Billing workflows to up-/ and downgrade your Prisma Postgres pricing plan. - Ready-to-deploy fullstack Next.js [template](https://vercel.com/templates/next.js/prisma-postgres) with authentication. ## Usage > **Note**: The easiest way to use the Prisma Postgres extension is via the [Next.js Auth Template](https://vercel.com/templates/next.js/prisma-postgres). ### Install the extension To install the extension, click **Install** at the top of the [Prisma Postgres integration page](https://www.vercel.com/marketplace/prisma). The integration will now show up on your list of integrations, e.g. `https://vercel.com//~/integrations`. ### Create a new database Once installed, you can navigate to the **Storage** tab and click **Create Database**. Select **Prisma Postgres** and click **Continue**. Then select the **Region** for the database and a **Pricing Plan**, and click **Continue** again. Finally, give the database a **Name** and click **Create**. The database is now ready and can be connected to your Vercel projects. ### Connect database to Vercel project In your Vercel project, you can now click the **Storage** tab, select the database you just created and then click **Connect**. This will automatically set the `DATABASE_URL` environment variable in that project and enable your application to access your newly created Prisma Postgres instance. ### Viewing and editing data in Prisma Studio To view and edit the data in your Prisma Postgres instance, you can use the local version of [Prisma Studio](/orm/tools/prisma-studio). In the local version of your project where you have your `DATABASE_URL` set, run the following command to open Prisma Studio: ```terminal npx prisma studio ``` ## Additional considerations ### Ensure your project uses the `DATABASE_URL` environment variable Ensure that the data source in your `schema.prisma` file is configured to use the `DATABASE_URL` environment variable: ```prisma // schema.prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` ### Generate Prisma Client in a `postinstall` script in `package.json` To ensure the generated Prisma Client library is available on your deployed Vercel project, you should add a `postinstall` script to the `scripts` section of your `package.json` file: ```js file=package.json { // ... "scripts": { // ... // add-next-line "postinstall": "prisma generate --no-engine" } // } ``` The `--no-engine` flag ensures that the query engine binary is kept out of the generated Prisma Client library. It's not needed when using Prisma Postgres. ## Example: Deploy a Next.js template with Prisma Postgres To get started you can deploy our [Next.js starter template](https://vercel.com/templates/next.js/prisma-postgres) and connect via Prisma Postgres instance during the deployment flow. --- # Firebase Studio URL: https://www.prisma.io/docs/postgres/integrations/idx ## Overview If you want to explore Prisma Postgres without leaving your browser, you can try it out the via Google's [Firebase Studio](https://studio.firebase.google.com/), a fully-fledged online IDE: 1. Open the [**Prisma**](https://pris.ly/idx-starter) template. 1. Select **Prisma Postgres** as your database. 1. Give a **Name** to your workspace and click the **Create** button. 1. Wait until the Firebase Studio workspace has initialized and then follow the instructions in the README. --- # Integrations URL: https://www.prisma.io/docs/postgres/integrations/index Learn how to use Prisma Postgres via 3rd party integrations. ## In this section --- # Getting started URL: https://www.prisma.io/docs/postgres/getting-started The easiest ways to get started with Prisma Postgres is by following these guides: - [**Start from scratch**](/getting-started/quickstart-prismaPostgres) - [**Import data from an existing database**](/getting-started/prisma-postgres/import-from-existing-database-postgresql) If you are looking to explore Prisma Postgres in a fullstack project, check out these resources: - [**Build a fullstack app with Next.js 15**](/guides/nextjs) - [**Next.js 15 example app**](https://github.com/prisma/nextjs-prisma-postgres-demo) (including authentication) --- # Overview URL: https://www.prisma.io/docs/postgres/overview [Prisma Postgres](https://www.prisma.io/postgres?utm_source=docs) is a managed PostgreSQL database service that easily lets you create a new database, interact with it through Prisma ORM, and build applications that start small and cheap but can scale to millions of users. It supports the following workflows: - Schema migrations and queries (via [Prisma ORM](https://www.prisma.io/orm)) - Connection pooling and caching (via [Prisma Accelerate](https://www.prisma.io/accelerate)) ## Billing ### Usage-based pricing Prisma Postgres charges for: - number of operations - storage (in GiB) An _operation_ is counted each time you perform a create, read, update, or delete—regardless of how simple or complex the underlying SQL is. Whether it’s a single-row lookup or complex JOIN query, it still counts as one operation and costs the same. By treating every operation equally, you don’t have to worry about write-heavy workloads driving up your bill or high-bandwidth requests ballooning costs unexpectedly. You can directly correlate your database costs to real product usage and user behavior, making forecasting and budgeting simple and predictable. Learn more on our [pricing page](https://www.prisma.io/pricing). ### Spend limits Prisma Postgres allows you to set limits to ensure you never get a surprise bill. You'll receive alerts when you reach 75% of your set limit, and if you reach 100%, your database will be paused. This ensures you'll never have an unexpected bill, and you can always be in complete control of your spending. ## Bundling with Prisma Accelerate Prisma Postgres comes bundled with [Prisma Accelerate](/accelerate). ### Using the Client extension for Prisma Accelerate (required) Because all traffic to Prisma Postgres is routed through Accelerate's connection pool, your project must have the [`@prisma/extension-accelerate`](https://www.npmjs.com/package/@prisma/extension-accelerate) npm package installed. The extension then needs to be applied to the `PrismaClient` instance you use to interact with your database: ```ts import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' const prisma = new PrismaClient() .$extends(withAccelerate()) ``` ## Technical details ### PostgreSQL version Prisma Postgres is based **PostgreSQL v17**. ### Architecture Prisma Postgres uses a unique architecture to deliver unmatched efficiency, safety and ease of use. It is deployed on bare metal servers using unikernels (think: "hyper-specialized operating systems"). Learn more about the architecture in this article: [Prisma Postgres®: Building a Modern PostgreSQL Service Using Unikernels & MicroVMs](https://pris.ly/ppg-early-access?utm_source=docs). --- # Connection pooling URL: https://www.prisma.io/docs/postgres/connection-pooling Prisma Postgres includes built-in connection pooling, enabled by [Prisma Accelerate](/accelerate/). This reduces the number of direct database connections and helps manage concurrent requests efficiently. For more details, see the [connection pooling documentation](/accelerate/connection-pooling). --- # Caching URL: https://www.prisma.io/docs/postgres/caching Prisma Postgres comes with a built-in global cache (enabled by [Prisma Accelerate](/accelerate/)) that helps you speed up your database queries. You can cache results on a per-query level using the `cacheStrategy` option in any Prisma ORM query, e.g.: ```ts const users = await prisma.user.findMany({ cacheStrategy: { ttl: 60, swr: 60 } }) ``` Check out the [caching](/accelerate/caching) documentation for details. --- # Backups URL: https://www.prisma.io/docs/postgres/backups Prisma Postgres takes full snapshots of your database every 24 hours to back up your data. If you are on a Pro, Business, or Enterprise plan, you can [reach out to our Support team](mailto:support@prisma.io) to get access to a past snapshot. Backups are not available on the Starter plan. Please reach out from the email address associated with your Prisma Console account to help us verify your account quickly and expedite the restoration process. Please note that any database changes or events that occurred after the most recent snapshot may not be restored. For more details about backup availability and plan-specific features, visit our [pricing page](https://www.prisma.io/pricing). In the future, Prisma Postgres will provide more fine-grained backup mechanisms based on user specific configurations and with point-in-time restore functionality. ## Creating Backup file via `@prisma/ppg-tunnel` If you would like to create a backup file of your database, you can use the `@prisma/ppg-tunnel` CLI. This is useful for migrating data between databases or creating a local copy of your database. ## Prerequisites Before you begin, make sure you have: - **Node.js** installed (version 16 or higher). - **PostgreSQL CLI Tools** (`pg_dump`) for creating backups. Use Postgres version 17 as Prisma Postgres is based on this version. - A **Database connection string** for your Prisma Postgres database. To create backups, ensure you have the PostgreSQL command-line tools installed. Run the following commands based on your operating system: ```terminal brew install postgresql@17 which pg_dump which pg_restore ``` ```terminal # Download from the official PostgreSQL website: # https://www.postgresql.org/download/windows/ # During installation, select "Command Line Tools". # Then verify with: where pg_dump where pg_restore ``` ```terminal sudo apt-get update sudo apt-get install postgresql-client-17 which pg_dump which pg_restore ``` :::tip If you installed PostgreSQL but still see a “command not found” error for pg_dump or pg_restore, ensure your installation directory is in your system’s PATH environment variable. ::: :::note Please make sure that you are installing Postgresql version 17. Other versions may cause errors during the backup process. ::: ### 1. Connecting to the database directly with `@prisma/ppg-tunnel` In your terminal, run `npx @prisma/ppg-tunnel` to establish a secure tunnel to your database. If you already have a `.env` file in your current directory with `DATABASE_URL` set, the tunnel CLI will automatically pick it up—no need to manually export it. However, if you haven't set up a `.env` file, you'll need to set the `DATABASE_URL` environment variable explicitly. To set environment variable (with your actual database URL): ```bash export DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI..." ``` :::note If you explicitly set `DATABASE_URL` in your terminal, that value will take precedence over the one in your `.env` file. ::: Run the tunnel: ```bash npx @prisma/ppg-tunnel --host 127.0.0.1 --port 5432 ``` You can provide any other port if you wish. A random port is assigned if no port value is provided. You should see output similar to: ```cmd Prisma Postgres auth proxy listening on 127.0.0.1:5432 🚀 Your connection is authenticated using your Prisma Postgres API key. ... ============================== hostname: 127.0.0.1 port: 5432 username: password: ============================== ``` :::note Please note that the port you will see in your output will be a randomly assigned port which may be different from the one mentioned here. Also, Keep this terminal window open so the tunnel remains active! If you close it, the tunnel disconnects. ::: Copy the port number from the terminal output, you’ll need it in the next step for the `pg_dump` command. ### 2. Creating the Backup with `pg_dump` With the tunnel running, you can now dump the database by running the following command: ```bash PGSSLMODE=disable \ pg_dump \ -h 127.0.0.1 \ -p 5432 \ -Fc \ -v \ -d postgres \ -f ./mydatabase.bak \ && echo "-complete-" ``` `PGSSLMODE=disable` indicates SSL is not required locally because the tunnel already encrypts the connection. ``` `-h` is the host (127.0.0.1) `-p` is the port, which should match the one from the tunnel output. `-Fc` uses the custom format for backups, recommended for pg_restore. `-d` postgres is the default database name used in Prisma Postgres. `-f` ./mydatabase.bak specifies the backup file name and location. `-v` runs pg_dump in verbose mode. ``` This should create your backup file named `mydatabase.bak` in the current directory. --- # TCP tunnel URL: https://www.prisma.io/docs/postgres/tcp-tunnel Prisma Postgres can be accessed securely via a TCP tunnel using the [`@prisma/ppg-tunnel`](https://www.npmjs.com/package/@prisma/ppg-tunnel) package, an authentication proxy designed for local database workflows. This package establishes a secure connection to Prisma Postgres through a local TCP server, enabling secure access while automatically handling traffic routing and authentication. :::note This is an [Early Access](/platform/maturity-levels#early-access) feature of Prisma Postgres. It is not recommended for production use and is not intended for application-level access. While in Early Access, usage of the TCP tunnel will be free of charge. ::: ### Prerequisites - Node.js installed on your machine - A [Prisma Postgres](/postgres) database connection string set as an environment variable called `DATABASE_URL` ### Exporting environment variables The tunnel expects you to have the following `DATABASE_URL` environment variable set to the connection URL of your Prisma Postgres instance. If you are running the tunnel command from your project where an `.env` file has `DATABASE_URL` already set, you can skip this step as the tunnel will automatically pick it up. To export the `DATABASE_URL` environment variable temporarily in a terminal session: ```terminal export DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=API_KEY" ``` ```terminal export DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=API_KEY" ``` ```terminal set DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=API_KEY" ``` Replace the `API_KEY` placeholder with the API key value of your Prisma Postgres instance. ### Starting the TCP tunnel To start the proxy server, run the following command: ```terminal npx @prisma/ppg-tunnel ``` ```code no-copy wrap Prisma Postgres auth proxy listening on 127.0.0.1:52604 🚀 Your connection is authenticated using your Prisma Postgres API key. ... ============================== hostname: 127.0.0.1 port: 52604 username: password: ============================== ``` This will start the tunnel on a randomly assigned TCP port. The proxy automatically handles authentication, so any database credentials are accepted. The tunnel also encrypts traffic, meaning clients should be set to not require SSL. You can now connet to your Prisma Postgres editor using your favorite PostgreSQL client, e.g. `psql` or a GUI like [TablePlus](/postgres/tooling#2a-connect-to-prisma-postgres-using-tableplus) or [DataGrip](/postgres/tooling#2b-connect-to-prisma-postgres-using-datagrip). To do so, you only need to provide the **`host`** and **`port`** from the output above. The TCP tunnel will handle authentication via the API key in your Prisma Postgres connection URL, so you can omit the values for **`username`** and **`password`**. ### Customizing host and port By default, the tunnel listens on `127.0.0.1` and assigns a random port. Since it provides access to your Prisma Postgres database, it should only be exposed within a trusted network. You can specify a custom host and port using the `--host` and `--port` flags: ```terminal npx @prisma/ppg-tunnel --host 127.0.0.1 --port 5432 ``` ## Next steps The local tunnel enables you to access Prisma Postgres from 3rd party database editors such as Postico, DataGrip, TablePlus and pgAdmin. Learn more in this [section](/postgres/tooling). ## Security considerations When using the TCP tunnel, keep the following in mind: - The tunnel does not support schema management (i.e., DDL queries outside of Prisma Migrate). - The tunnel should not be exposed to untrusted networks. - Always store API keys securely and avoid hardcoding them. - Ensure that only necessary users have direct access to the Prisma Postgres database. --- # MCP Server URL: https://www.prisma.io/docs/postgres/mcp-server The [Model-Context-Protocol](https://modelcontextprotocol.io/introduction) (MCP) gives LLMs a way to call APIs and thus access external systems in a well-defined manner. Prisma's MCP server gives LLMs the ability to manage Prisma Postgres databases (e.g. spin up new database instances or run schema migrations). :::note The Prisma MCP server is available via the Prisma CLI command `prisma platform mcp --early-access` and is currently available in Early Access. See below for how to integrate it in your favorite AI tool. It uses the `stdio` transport mechanism. ::: ## Usage The Prisma MCP server follows the standard JSON-based configuration for MCP servers. Here's what it looks like: ```json { "mcpServers": { "Prisma": { "command": "npx", "args": ["-y", "prisma", "mcp"] } } } ``` ## Sample prompts Here are some sample prompts you can use when the MCP server is running: - Log me into the Prisma Console. - Create a database in the US region. - Create a new `Product` table in my database. ## Integrating in AI tools AI tools have different ways of integrating MCP servers. In most cases, there are dedicated configuration files in which you add the JSON configuration from above. The configuration contains a command for starting the server that'll be executed by the respective tool so that the server is available to its LLM. In this section, we're covering the config formats of the most popular AI tools. ### Cursor To learn more about Cursor's MCP integration, check out the [Cursor MCP docs](https://docs.cursor.com/context/model-context-protocol#configuration-locations). #### Add via Cursor Settings UI When opening the **Cursor Settings**, you can add the Prisma MCP Server as follows: 1. Select **MCP** in the settings sidenav 1. Click **+ Add new global MCP server** 1. Add the `Prisma` snippet to the `mcpServers` JSON object: ```json { "mcpServers": { "Prisma": { "command": "npx", "args": ["-y", "prisma", "mcp"] } } } ``` #### Global configuration Adding it via the **Cursor Settings** settings will modify the global `~/.cursor/mcp.json` config file. In this case, the Prisma MCP server will be available in _all_ your Cursor projects: ```json file=\~/.cursor/mcp.json { "mcpServers": { "Prisma": { "command": "npx", "args": ["-y", "prisma", "mcp"] }, // other MCP servers } } ``` #### Project configuration If you want the Prisma MCP server to be available only in specific Cursor projects, add it to the Cursor config of the respective project inside the `.cursor` directory in the project's root: ```json file=.cursor/mcp.json { "mcpServers": { "Prisma": { "command": "npx", "args": ["-y", "prisma", "mcp"] }, // other MCP servers } } ``` ### Windsurf To learn more about Windsurf's MCP integration, check out the [Windsurf MCP docs](https://docs.codeium.com/windsurf/mcp). #### Add via Windsurf Settings UI When opening the **Windsurf Settings** (via **Windsurf - Settings** > **Advanced Settings or Command Palette** > **Open Windsurf Settings Page**), you can add the Prisma MCP Server as follows: 1. Select **Cascade** in the settings sidenav 1. Click **Add Server** 1. Add the `Prisma` snippet to the `mcpServers` JSON object: ```json { "mcpServers": { "Prisma": { "command": "npx", "args": ["-y", "prisma", "mcp"] } } } ``` #### Global configuration Adding it via the **Windsurf Settings** will modify the global `~/.codeium/windsurf/mcp_config.json` config file. Alternatively, you can also manually add it to that file: ```json file=~/.codeium/windsurf/mcp_config.json { "mcpServers": { "Prisma": { "command": "npx", "args": ["-y", "prisma", "mcp"] }, // other MCP servers } } ``` ### Claude Code Claude Code is a terminal-based AI tool where you can add MCP server using the `claud mcp add` command: ```terminal claude mcp add prisma npx prisma mcp ``` Learn more in the [Claude Code MCP docs](https://docs.anthropic.com/en/docs/agents-and-tools/claude-code/tutorials#configure-mcp-servers). ### Claude Desktop Follow the instructions in the [Claude Desktop MCP docs](https://modelcontextprotocol.io/quickstart/user#2-add-the-filesystem-mcp-server) to create the required configuration file: - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json` - Windows: `%APPDATA%\Claude\claude_desktop_config.json` Then add the JSON snippet to that configuration file: ```json { "mcpServers": { "Prisma": { "command": "npx", "args": ["-y", "prisma", "mcp"] }, // other MCP servers } } ``` ### OpenAI Agents SDK Here's an example for using the Prisma MCP server in a Python script via the OpenAI Agents SDK: ```python from openai import AsyncOpenAI from openai.types.beta import Assistant from openai.beta import AsyncAssistantExecutor from openai.experimental.mcp import MCPServerStdio from openai.types.beta.threads import Message, Thread from openai.types.beta.tools import ToolCall # Async context required for MCPServerStdio import asyncio async def main(): # Start the Prisma MCP server using stdio async with MCPServerStdio( params={ "command": "npx", "args": ["-y", "prisma", "mcp"] } ) as prisma_server: # Optional: view available tools tools = await prisma_server.list_tools() print("Available tools:", [tool.name for tool in tools]) # Set up the agent with MCP server agent = Assistant( name="Prisma Assistant", instructions="Use the Prisma tools to help the user with database tasks.", mcp_servers=[prisma_server], ) executor = AsyncAssistantExecutor(agent=agent) # Create a thread and send a message thread = Thread(messages=[Message(role="user", content="Create a new user in the database")]) response = await executor.run(thread=thread) print("Agent response:") for message in response.thread.messages: print(f"{message.role}: {message.content}") # Run the async main function asyncio.run(main()) ``` --- # Tooling URL: https://www.prisma.io/docs/postgres/tooling You can view and edit your data in Prisma Postgres using either [Prisma Studio](/orm/tools/prisma-studio) or 3rd party database editors. ## Viewing and editing data in Prisma Studio With Prisma Postgres, a hosted version of [Prisma Studio](/orm/tools/prisma-studio) is available for you in of your project. In your project environment in the [Platform Console](https://console.prisma.io/), select the **Studio** tab in the left-hand navigation to view and edit your data: ![View of Prisma Studio open in the console.](/img/ppg-studio.png) You can also run Prisma Studio locally by running: ```terminal npx prisma studio ``` This should start a live server in `http://localhost:5555` where you can visit and interact with your database. ## Connecting to Prisma Postgres instance with 3rd party database editors You can connect to your Prisma Postgres instance using third party database editors like pgAdmin, TablePlus, Postico etc using [`@prisma/ppg-tunnel` package](https://www.npmjs.com/package/@prisma/ppg-tunnel). See the example below to connect using TablePlus. ### 1. Create a TCP tunnel to access Prisma Postgres directly If you already have a `.env` file in your current directory with `DATABASE_URL` set, the tunnel CLI will automatically pick it up, no need to manually export it. However, if you haven't set up a `.env` file, you'll need to set the `DATABASE_URL` environment variable explicitly. In your terminal, to set the environment variable `DATABASE_URL` referring to your Prisma Postgres instance which you want to connect to (be sure to replace the `API_KEY` placeholder with the API key value of your Prisma Postgres instance): ```terminal export DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=API_KEY" ``` ```terminal export DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=API_KEY" ``` ```cmd set DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=API_KEY" ``` :::note If you explicitly set `DATABASE_URL` in your terminal, that value will take precedence over the one in your `.env` file. ::: Run the following command to connect to your Prisma Postgres instance via `@prisma/ppg-tunnel` package: ```terminal npx @prisma/ppg-tunnel --host 127.0.0.1 --port 52604 ``` ```no-copy wrap Prisma Postgres auth proxy listening on 127.0.0.1:52604 🚀 Your connection is authenticated using your Prisma Postgres API key. ... ============================== hostname: 127.0.0.1 port: 52604 username: password: ============================== ``` Copy the **`port`** from the output above, you will need it in the next step. Keep this tunnel process running while you are using the database editor to maintain the connection. ### 2a. Connect to Prisma Postgres using TablePlus Based on the database editor you are using, you can connect to your Prisma Postgres instance using the details you obtained from the output of the `@prisma/ppg-tunnel` package. To add the connection string in TablePlus: 1. Open TablePlus and click on the **+** icon to add a new connection. 2. Select **PostgreSQL** as the database type. 3. Enter the following details: - **Name**: Any name you want to give to your connection. - **Host**: `127.0.0.1` in this case. - **Port**: The **`port`** number you obtained from the output of the `@prisma/ppg-tunnel` package. - **User**: This will be ignored due to the tunnel, you can provide any value here. - **Password**: This will be ignored due to the tunnel, you can provide any value here. 4. Click on **Connect** to connect to your Prisma Postgres instance. ![View of TablePlus connected to Prisma Postgres via tunnel](/img/ppg-tableplus.png) ### 2b. Connect to Prisma Postgres using DataGrip Based on the database editor you are using, you can connect to your Prisma Postgres instance using the details you obtained from the output of the `@prisma/ppg-tunnel` package. To add the connection string in DataGrip: 1. Open DataGrip and click on the **+** icon and select "Datasource". 2. Select **PostgreSQL** as the database type. 3. Enter the following details: - **Name**: Any name you want to give to your connection. - **Host**: `127.0.0.1` in this case. - **Port**: The **`port`** number you obtained from the output of the `@prisma/ppg-tunnel` package. - **User**: This will be ignored due to the tunnel, you can keep this field empty. - **Password**: This will be ignored due to the tunnel, you can keep this field empty. - **URL**: In the URL append the following query parameter `?sslmode=disable` to the end of the URL. 4. Click on **Test Connection** to ensure that DataGrip can connect to your Prisma Postgres instance. Once successful, click **OK** to save the connection. ![View of DataGrip connected to Prisma Postgres via tunnel](/img/ppg-datagrip.png) ### 2c. Connect to Prisma Postgres using DBeaver Based on the database editor you are using, you can connect to your Prisma Postgres instance using the details you obtained from the output of the `@prisma/ppg-tunnel` package. To add the connection string in DBeaver: 1. Open DBeaver and click on the **New Database Connection** button or **File** > **New** to add a new connection. 2. Select **PostgreSQL** as the database type. 3. Select **URL** option in Connect by section. 4. Enter the URL in this format: - **URL**: Your URL should be in this format: `jdbc:postgresql://localhost:52604/postgres?sslmode=disable`. Here make sure that you enter the port number you obtained from the output of the `@prisma/ppg-tunnel` package. In this case, the port number is `52604`. There is no need to enter Username or Password as authentication is manged by Tunnel. 5. Click on **Test Connection** to ensure that DBeaver can connect to your Prisma Postgres instance. If successful, click **Finish**. ![View of DBeaver connected to Prisma Postgres via tunnel](/img/ppg-dbeaver.png) ### 2d. Connect to Prisma Postgres using Postico Based on the database editor you are using, you can connect to your Prisma Postgres instance using the details you obtained from the output of the `@prisma/ppg-tunnel` package. To add the connection string in Postico: 1. Open Postico and click on the **New Server** button to add a new connection. 2. Enter the following details: - **Name**: Any name you want to give to your connection. - **Host**: `127.0.0.1` in this case. - **Port**: The **`port`** number you obtained from the output of the `@prisma/ppg-tunnel` package. - **User**: This will be ignored due to the tunnel, you can keep this field empty. - **Password**: This will be ignored due to the tunnel, you can keep this field empty. 3. Check "Pre-Connect Shell Script" and enter: ```sh cat < --- > **Note**: Postgres, PostgreSQL and the Slonik Logo are trademarks or registered trademarks of the PostgreSQL Community Association of Canada, and used with their permission --- # Getting started with Prisma Accelerate URL: https://www.prisma.io/docs/accelerate/getting-started ## Prerequisites To get started with Accelerate, you will need the following: - A [Prisma Data Platform account](https://console.prisma.io) - A project that uses [Prisma Client](/orm/prisma-client) `4.16.1` or higher. If your project is using interactive transactions, you need to use `5.1.1` or higher. (We always recommend using the latest version of Prisma.) - A hosted PostgreSQL, MySQL/MariaDB, PlanetScale, CockroachDB, or MongoDB database ## 1. Enable Accelerate Navigate to your Prisma Data Platform project, choose an environment, and enable Accelerate by providing your database connection string and selecting the region nearest your database. :::note If you require IP allowlisting or firewall configurations with trusted IP addresses, enable Static IP for enhanced security. Learn more on [how to enable static IP for Accelerate in the Platform Console](/accelerate/static-ip). ::: ## 2. Add Accelerate to your application ### 2.1. Update your database connection string Once enabled, you'll be prompted to generate an API key that you'll use in your new Accelerate connection string to authenticate requests. Replace your direct database url with your new Accelerate connection string. ```env file=.env # New Accelerate connection string with generated API_KEY DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=__API_KEY__" # Previous (direct) database connection string # DATABASE_URL="postgresql://user:password@host:port/db_name?schema=public" ``` Your updated connection string will be used as the datasource `url` in your Prisma schema file; ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` Prisma Migrate and Introspection do not work with a `prisma://` connection string. In order to continue using these features add a new variable to the `.env` file named `DIRECT_DATABASE_URL` whose value is the direct database connection string: ```env file=.env highlight=3;add showLineNumbers DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=__API_KEY__" DIRECT_DATABASE_URL="postgresql://user:password@host:port/db_name?schema=public" ``` Then in your Prisma schema's `datasource` block add a field named `directUrl` with the following: ```prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") //add-next-line directUrl = env("DIRECT_DATABASE_URL") } ``` Migrations and introspections will use the `directUrl` connection string rather than the one defined in `url` when this configuration is provided. > `directUrl` is useful for you to carry out migrations and introspections. However, you don't need `directUrl` to use Accelerate in your application. :::note If you are using Prisma with PostgreSQL, there is no need for `directUrl`, as Prisma Migrate and Introspection work with the `prisma+postgres://` connection string. ::: ### 2.2. Install the Accelerate Prisma Client extension :::info 💡 Accelerate requires [Prisma Client](/orm/prisma-client) version `4.16.1` or higher and [`@prisma/extension-accelerate`](https://www.npmjs.com/package/@prisma/extension-accelerate) version `1.0.0` or higher ::: Install the latest version of Prisma Client and Accelerate Prisma Client extension ```terminal npm install @prisma/client@latest @prisma/extension-accelerate ``` ### 2.3. Generate Prisma Client for Accelerate If you're using Prisma version `5.2.0` or greater, Prisma Client will automatically determine how it should connect to the database depending on the protocol in the database connection string. If the connection string in the `DATABASE_URL` starts with `prisma://`, Prisma Client will try to connect to your database using Prisma Accelerate. When using Prisma Accelerate in long-running application servers, such as a server deployed on AWS EC2, you can generate the Prisma Client by executing the following command: ```terminal npx prisma generate ``` When using Prisma Accelerate in a Serverless or an Edge application, we recommend you to run the following command to generate Prisma Client: ```terminal npx prisma generate --no-engine ``` The `--no-engine` flag prevents a Query Engine file from being included in the generated Prisma Client, this ensures the bundle size of your application remains small. :::warning If your Prisma version is below `5.2.0`, generate Prisma Client with the `--accelerate` option: ```terminal npx prisma generate --accelerate ``` If your Prisma version is below `5.0.0`, generate Prisma Client with the `--data-proxy` option: ```terminal npx prisma generate --data-proxy ``` ::: ### 2.4. Extend your Prisma Client instance with the Accelerate extension Add the following to extend your existing Prisma Client instance with the Accelerate extension: ```ts import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' const prisma = new PrismaClient().$extends(withAccelerate()) ``` If you are going to deploy to an edge runtime (like Cloudflare Workers, Vercel Edge Functions, Deno Deploy, or Supabase Edge Functions), use our edge client instead: ```ts import { PrismaClient } from '@prisma/client/edge' import { withAccelerate } from '@prisma/extension-accelerate' const prisma = new PrismaClient().$extends(withAccelerate()) ``` If VS Code does not recognize the `$extends` method, refer to [this section](/accelerate/faq#vs-code-does-not-recognize-the-extends-method) on how to resolve the issue. #### Using the Accelerate extension with other extensions or middleware Since [extensions are applied one after another](/orm/prisma-client/client-extensions#conflicts-in-combined-extensions), make sure you apply them in the correct order. Extensions cannot share behavior and the last extension applied takes precedence. If you are using [Prisma Optimize](/optimize) in your application, make sure you apply it _before_ the Accelerate extension. For example: ```ts const prisma = new PrismaClient().$extends(withOptimize()).$extends(withAccelerate()) ``` If you are using [Prisma Middleware](/orm/prisma-client/client-extensions/middleware) in your application, make sure they are added before any Prisma Client extensions (like Accelerate). For example: ```ts const prisma = new PrismaClient().$use(middleware).$extends(withAccelerate()) ``` ### 2.5. Use Accelerate in your database queries The `withAccelerate` extension primarily does two things: - Gives you access to the `cacheStrategy` field within each applicable model method that allows you to define a cache strategy per-query. - Routes all of your queries through a connection pooler. #### No cache strategy to only use connection pool If you simply want to take advantage of Accelerate's connection pooling feature without applying a cache strategy, you may run your query the same way you would have without Accelerate. By enabling Accelerate and supplying the Accelerate connection string, your queries now use the connection pooler by default. #### Define a cache strategy Update a query with the new `cacheStrategy` property which allows you to define a cache strategy for that specific query: ```ts const user = await prisma.user.findMany({ where: { email: { contains: 'alice@prisma.io', }, }, cacheStrategy: { swr: 60, ttl: 60 }, }) ``` In the example above, `swr: 60` and `ttl: 60` means Accelerate will serve cached data for 60 seconds and then another 60 seconds while Accelerate fetches fresh data in the background. You should now see improved performance for your cached queries. For information about which strategy best serves your application, see [Select a cache strategy](/accelerate/caching#selecting-a-cache-strategy). :::info As of Prisma version `5.2.0` you can use Prisma Studio with the Accelerate connection string. ::: #### Invalidate the cache and keep your cached query results up-to-date If your application requires real-time or near-real-time data, cache invalidation ensures that users see the most current data, even when using a large `ttl` (Time-To-Live) or `swr` (Stale-While-Revalidate) [cache strategy](/accelerate/caching#cache-strategies). By invalidating your cache, you can bypass extended caching periods to show live data whenever it's needed. For example, if a dashboard displays customer information and a customer’s contact details change, cache invalidation allows you to refresh only that data instantly, ensuring support staff always see the latest information without waiting for the cache to expire. To invalidate a cached query result, you can add tags and then use the `$accelerate.invalidate` API. :::note On-demand cache invalidation is available with our paid plans. For more details, please see our [pricing](https://www.prisma.io/pricing#accelerate). ::: To invalidate the query below: ```ts await prisma.user.findMany({ where: { email: { contains: "alice@prisma.io", }, }, cacheStrategy: { swr: 60, ttl: 60, // highlight-start tags: ["emails_with_alice"], // highlight-end }, }); ``` You need to provide the cache tag in the `$accelerate.invalidate` API: ```ts try { // highlight-start await prisma.$accelerate.invalidate({ tags: ["emails_with_alice"], }); // highlight-end } catch (e) { if (e instanceof Prisma.PrismaClientKnownRequestError) { // The .code property can be accessed in a type-safe manner if (e.code === "P6003") { console.log( "You've reached the cache invalidation rate limit. Please try again shortly." ); } } throw e; } ``` --- # Connection Pooling URL: https://www.prisma.io/docs/accelerate/connection-pooling :::info To learn more about connection pooling generally, be sure to check out [Prisma's Data Guide](https://www.prisma.io/dataguide/database-tools/connection-pooling) for a comprehensive overview on what connection pooling is, what it seeks to address, and how it works. ::: Accelerate provides built-in connection pooling by default. By using Accelerate, you get the benefits of connection pooling without having to configure anything. The efficient management of database connections allows the database to process more queries without exhausting the available database connections, making your application more scalable. In some cases, however, it may be beneficial to further configure connection pooling in order to optimize the performance of your application. :::note This document focuses on the connection pooling features of Prisma Accelerate. For more information about the internal connection pool of Prisma ORM specifically, see our [ORM connection pooling documentation](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool). ::: ### Connection Pooling in Accelerate By default, Accelerate has a connection limit of `10`. This means that Prisma Accelerate will open at most 10 database connections to your database per Prisma Schema used in Accelerate. For the Starter plan, this is also the maximum connection limit. In most cases, this connection limit is sufficient. However, in high traffic or heavy compute environments, you may need to [increase this value](#configuring-the-connection-pool-size). If your project is on the [Pro plan](https://www.prisma.io/pricing), the maximum connection limit is `100`. For [Business plan](https://www.prisma.io/pricing) projects the maximum is `1000`. ### Configuring the connection pool size When not using Prisma Accelerate, you can configure the connection pool of Prisma ORM [via the connection string](/orm/prisma-client/setup-and-configuration/databases-connections/connection-pool#setting-the-connection-pool-size). When using Prisma Accelerate *this feature is not available*. Instead, you can configure the connection pool size in your Platform project via the `Connection limit` setting [on Accelerate setup](/accelerate/getting-started). #### Autoscaling Autoscaling allows Accelerate to dynamically allocate resources based on your application's traffic. As consistent usage approaches the current connection limit, Accelerate will begin allocating new resources to handle the increased load. If traffic continues to rise, Accelerate will scale up further. Conversely, when traffic decreases, Accelerate will scale down accordingly. *To provide more context, Accelerate horizontally scales your environment by distributing the total available connections across multiple Query Engine instances. For example:* - If your environment connection limit is set to 1000, Accelerate will scale up to multiple Query Engine instances (e.g., 100 instances). - Each Query Engine instance is then assigned a share of the total connections— in this case, 10 connections per instance. - This is why an individual Query Engine instance reports a connection limit of 10, even though the total connection limit for the environment is 1000. *This scaling mechanism ensures that your application can handle higher traffic loads by increasing the number of Query Engine instances while keeping the connection pool management efficient and distributed.* Autoscaling is enabled when the Accelerate connection limit is set above the default value. This feature is not available on the Starter plan. The maximum value of your Accelerate connection limit is based on your [Prisma Data Platform plan](https://www.prisma.io/pricing). | Plan | Maximum Connection Limit | |------------|--------------------------------------| | Starter | 10 | | Pro | 100 | | Business | 1000 | | Enterprise | [Contact Us](mailto:sales@prisma.io) | ### Configuring the connection pool timeout The connection pool timeout is the maximum number of seconds that a query will block while waiting for a connection from Accelerate's internal connection pool. This occurs if the number of concurrent requests exceeds the connection limit, resulting in queueing of additional requests until a free connection becomes available. An exception is thrown if a free connection does not become available within the pool timeout. The connection pool timeout can be disabled by setting the value to 0. Similar to the connection pool size, you may also configure the connection pool timeout via the _database connection string_. To adjust this value, you may add the `pool_timeout` parameter to the database connection string. For example: ```env no-copy postgresql://user:password@localhost:5432/db?connection_limit=10&pool_timeout=20 ``` The default value for `pool_timeout` is `10` seconds. ## Configuring query limits You can configure the minimum and maximum query response size, query duration, and transaction limits when using Prisma Accelerate from the **Settings** tab in your Accelerate-enabled project environment. ### Query timeout limit Accelerate has a default global timeout of `10s` for each query, configurable using the slider labeled **Query duration**, based on your subscription plan: | Plan | Starter | Pro | Business | |----------|---------------|--------------|---------------| | Query timeout | Up to 10 seconds | Up to 20 seconds | Up to 60 seconds | See the [troubleshooting guide](/accelerate/troubleshoot#p6004-querytimeout) and our [pricing page](https://www.prisma.io/pricing#accelerate) for more information. :::warning While you can increase the query timeout, it’s recommended to inspect and optimize your database queries if they take longer than 10 seconds. This helps reduce stress on your underlying database, as long-running queries often indicate a need for optimization. Learn more in the [troubleshooting guide](/accelerate/troubleshoot#p6004-querytimeout). ::: ### Interactive transactions query timeout limit Accelerate has a default global timeout of `15s` for each [interactive transaction](/orm/prisma-client/queries/transactions#interactive-transactions), configurable using the slider labeled **Transaction duration**, based on your subscription plan: | Plan | Starter | Pro | Business | |----------------------------|---------------|--------------|---------------| | Interactive transaction limit | Up to 15 seconds | Up to 30 seconds | Up to 90 seconds | See the [troubleshooting guide](/accelerate/troubleshoot#p6004-querytimeout) and our [pricing page](https://www.prisma.io/pricing#accelerate) for more information. When you set a higher interactive transaction timeout in the Prisma Console, you **must also** specify a matching `timeout` value in your interactive transaction query via timeout [transaction option](/orm/prisma-client/queries/transactions#transaction-options). Otherwise, transactions will still time out at the lower default (e.g., 5 seconds limit when no timeout value is specified). Here’s an example of how to set a 30-second timeout in your code: ```ts await prisma.$transaction( async (tx) => { // Your queries go here }, { timeout: 30000, // 30s } ); ``` :::warning While you can increase the interactive transaction timeout limit, it’s recommended to inspect and optimize your database transactions if they take longer than 15 seconds. Long-running transactions can negatively impact performance and often signal the need for optimization. Learn more in the [troubleshooting guide](/accelerate/troubleshoot#p6004-querytimeout) and review the [warning in the Interactive Transactions section](/orm/prisma-client/queries/transactions#interactive-transactions-1) in our documentation. ::: ### Response size limit Accelerate has a default global response size limit of `5MB`, configurable using the slider labeled **Response size**, based on your subscription plan: | Plan | Starter | Pro | Business | |----------|---------------|--------------|---------------| | Query size | Up to 5MB | Up to 10MB | Up to 20MB | See the [troubleshooting guide](/accelerate/troubleshoot#p6009-responsesizelimitexceeded) and our [pricing page](https://www.prisma.io/pricing#accelerate) for more information. :::warning While you can increase the query response size, it’s recommended to limit data retrieval to what you actually need. This improves database performance, reduces stress on your database, and makes your frontend applications more responsive. Queries exceeding 5 MB in size often indicate a need for optimization. Learn more in the [troubleshooting guide](/accelerate/troubleshoot#p6009-responsesizelimitexceeded). ::: --- # Caching URL: https://www.prisma.io/docs/accelerate/caching ## Cache strategies For all read queries in Prisma Client, you can define the `cacheStrategy` parameter that configures cache behavior. The cache strategy allows you to define two main characteristics of the cache: - **Time-to-live (TTL):** Duration in seconds a cached response is considered _fresh_. - **Stale-while-Revalidating (SWR):** Duration in seconds a stale cache response is considered acceptable while the cache is refreshed in the background ## Time-to-live (TTL) Time-to-Live (TTL) determines how long cached data is considered fresh. By specifying the `ttl` in seconds, you can control the duration for which data in the cache remains valid. When a read query is executed, if the cached response is within the `ttl` limit, Prisma Client retrieves the data from the cache without querying the database. If the cached data is not available or has expired, Prisma Client queries the database and stores the results in the cache for future requests. Use `ttl` in `cacheStrategy` and specify the TTL of the query in seconds: ```javascript await prisma.user.findMany({ cacheStrategy: { //add-next-line ttl: 60, }, }); ``` With a specified TTL of 60 seconds, the majority of requests will result in a cache hit throughout the TTL duration: ![TTL](/img/accelerate/ttl.png) TTL is useful for reducing database load and latency for data that does not require frequent updates. ### Invalidate the TTL and keep your cached query results up-to-date If your application requires real-time or near-real-time data, cache invalidation ensures that users see the most current data, even when using a large `ttl` (Time-To-Live). By invalidating your cache, you can bypass extended caching periods to show live data whenever it's needed. For example, if a dashboard displays customer information and a customer’s contact details change, TTL (Time-To-Live) settings ensure the cache automatically expires after a set duration. This allows the system to refresh only the updated data at the next access, ensuring support staff always see the latest information without manually refreshing the cache. However, in cases where immediate updates are required before the TTL expires, cache invalidation allows the system to proactively clear specific data from the cache. This forces a refresh of the updated information instantly, so support staff always have the most current details without waiting for the TTL to trigger. To invalidate a cached query result, you can add tags and then use the `$accelerate.invalidate` API. :::note On-demand cache invalidation is available with our paid plans. For more details, please see our [pricing](https://www.prisma.io/pricing#accelerate). ::: To invalidate the query below, you need to provide the cache tag in the `$accelerate.invalidate` API: ```ts await prisma.user.findMany({ cacheStrategy: { ttl: 60, //add-next-line tags: ["findMany_users"], }, }); // This is how you would invalidate the cached query above. //add-start await prisma.$accelerate.invalidate({ tags: ["findMany_users"], }); //add-end ``` ## Stale-While-Revalidate (SWR) Stale-While-Revalidate (SWR) allows you to control how long Accelerate can serve stale cache data while fetching fresh data in the background. When a read query is executed, Accelerate checks the age of the cached response against the `swr` duration. If the cache data is within the `swr` limit, Accelerate serves the stale data while simultaneously refreshing the cache by fetching the latest data from the database. Use `swr` in `cacheStrategy` and specify the SWR of the query in seconds: ```javascript await prisma.user.findMany({ cacheStrategy: { //add-next-line swr: 60, }, }); ``` When specifying a SWR of 60 seconds, the cache serves stale data until the cache refreshes itself in the background after each request: ![SWR](/img/accelerate/swr.png) ### Invalidate the SWR and keep your cached query results up-to-date If your application requires real-time or near-real-time data, cache invalidation ensures that users see the most current data, even when using a large `swr` (Stale-While-Revalidate). By invalidating your cache, you can bypass extended caching periods to show live data whenever it's needed. For example, consider a dashboard that displays stock levels for products in a warehouse. With SWR (Stale-While-Revalidate) settings, the dashboard can immediately display the last known stock data, even if it’s slightly outdated, while new data is fetched in the background. This ensures that staff can continue working with recent information without waiting, with the stock levels updating as soon as revalidation completes. However, in cases where stock data needs to be updated immediately—for instance, if a product is low in stock and the count needs real-time accuracy—cache invalidation allows the system to proactively clear specific data from the cache. This forces a refresh of the latest stock data instantly, so staff always have the most up-to-date information without waiting for SWR to complete the revalidation. To invalidate a cached query result, you can add tags and then use the `$accelerate.invalidate` API. :::note On-demand cache invalidation is available with our paid plans. For more details, please see our [pricing](https://www.prisma.io/pricing#accelerate). ::: To invalidate the query below, you need to provide the cache tag in the `$accelerate.invalidate` API: ```ts await prisma.user.findMany({ cacheStrategy: { swr: 60, //add-next-line tags: ["findMany_users"], }, }); // This is how you would invalidate the cached query above. //add-start await prisma.$accelerate.invalidate({ tags: ["findMany_users"], }); //add-end ``` ## Selecting a cache strategy Caching helps you improve query response times and reduce database load. However, it also means you might serve stale data to the client. Whether or not serving stale data is acceptable and to what extent depends on your use case. `ttl` and `swr` are parameters you can use the tweak the cache behavior. ### Cache strategy using TTL Use TTL to reduce database load when stale cached data is acceptable. #### Use case: Product catalog in e-commerce applications Consider an e-commerce application with a product catalog that doesn't frequently change. By setting a `ttl` of, let's say, 1 hour, Prisma Client can serve cached product data for subsequent user requests within that hour without hitting the database. This significantly reduces the database load and improves the response time for product listing pages. **When to invalidate:** If there are critical updates to the catalog, such as a major price change or product availability adjustment, the cache should be [invalidated](/accelerate/caching#on-demand-cache-invalidation) immediately to prevent customers from seeing outdated information. ### Cache strategy using SWR Use SWR to respond quickly to requests with minimal stale data. While it does not reduce database load, it can improve response times significantly. #### Use case: User profile in social media platforms Imagine a social media platform where user profiles are frequently accessed. By leveraging `swr` with a duration of, let's say, 5 minutes, Accelerate can serve the cached user profile information quickly, reducing the latency for profile pages. Meanwhile, in the background, it refreshes the cache after every request, ensuring that any updates made to the profile are eventually reflected for subsequent requests. **When to invalidate:** If a user makes significant updates to their profile, such as changing their profile picture or bio, the cache should be [invalidated](/accelerate/caching#on-demand-cache-invalidation) immediately to ensure that followers see the latest updates without waiting for the SWR refresh. ### Cache strategy using TTL + SWR For very fast response times and reduced database load, use both TTL and SWR. You can use this strategy to fine-tune your application’s tolerance for stale data. Use `ttl` and `swr` in `cacheStrategy` and specify the TTL and SWR of the query in seconds: ```javascript await prisma.user.findMany({ cacheStrategy: { //add-start ttl: 30, swr: 60, //add-end }, }); ``` When specifying a TTL of 30 seconds and SWR of 60 seconds, the cache serves fresh data for the initial 30 seconds. Subsequently, it serves stale data until the cache refreshes itself in the background after each request: ![ttl_and_swr.png](/img/accelerate/ttl_and_swr.png) #### Use case: News articles Consider a news application where articles are frequently accessed but don't require real-time updates. By setting a `ttl` of 2 hours and an `swr` duration of 5 minutes, Prisma Client can serve cached articles quickly, reducing latency for readers. As long as the articles are within the `ttl`, users get fast responses. After the `ttl` expires, Prisma Client continues to serve the stale articles for up to an additional 5 minutes, revalidating the cache with the latest news from the database in response to a new query. This helps maintain a balance between performance and freshness. **When to invalidate:** If a critical update or breaking news article is published, the cache should be [invalidated](/accelerate/caching#on-demand-cache-invalidation) immediately to ensure readers see the latest information without delay. This approach is especially useful for applications where certain news items may need to override the normal cache cycle for timeliness. ## On-demand cache invalidation If your application requires real-time or near-real-time data, cache invalidation ensures that users see the most current data, even when using a large `ttl` (Time-To-Live) or `swr` (Stale-While-Revalidate) [cache strategy](/accelerate/caching#cache-strategies). By invalidating your cache, you can bypass extended caching periods to show live data whenever it's needed. You can invalidate the cache using the [`$accelerate.invalidate` API](/accelerate/api-reference#accelerateinvalidate): :::note To programmatically invalidate cached queries, a paid plan is required. See our [pricing for more details](https://www.prisma.io/pricing#accelerate). ::: ```ts await prisma.user.findMany({ where: { email: { contains: "alice@prisma.io", }, }, cacheStrategy: { swr: 60, ttl: 60, // highlight-start tags: ["emails_with_alice"], // highlight-end }, }); ``` You need to provide the cache tag in the `$accelerate.invalidate` API: ```ts try { // highlight-start await prisma.$accelerate.invalidate({ tags: ["emails_with_alice"], }); // highlight-end } catch (e) { if (e instanceof Prisma.PrismaClientKnownRequestError) { // The .code property can be accessed in a type-safe manner if (e.code === "P6003") { console.log( "The cache invalidation rate limit has been reached. Please try again later." ); } } throw e; } ``` Explore the [demo app](https://pris.ly/test-cache-invalidation) to see how cached query results in Prisma Accelerate are invalidated on demand, shown in a clear timeline. ## Default cache strategy  Accelerate defaults to **no cache** to avoid unexpected issues. While caching can improve performance, incorrect usage may lead to errors. For instance, if a query is executed on a critical path without specifying a cache strategy, the result may be incorrect, with no clear explanation. This issue often arises when implicit caching is unintentionally left enabled. To avoid such problems, you must explicitly opt-in to caching. This ensures you are aware that caching is not enabled by default, preventing potential errors. > When no cache strategy is specified or during a cache miss, a Prisma Client with the Accelerate extension routes all queries to the database through a connection pool instance near the database region. --- # Static IP URL: https://www.prisma.io/docs/accelerate/static-ip You can enable static IP for Accelerate when your security setup requires IP allowlisting or if you're implementing firewalls that only permit access from trusted IPs, ensuring controlled and secure database connections. ![Result of enabling static IP Accelerate with a database using IP allowlisting](/img/accelerate/result-of-adding-static-ip-to-accelerate.png) :::info To enable static IP support for Accelerate within an existing or a new project environment, your workspace will need to be on our Pro or Business plans. Take a look at the [pricing page](https://www.prisma.io/pricing#accelerate) for more information. ::: ## Enable static IP in Accelerate You can opt-in to use static IP for Accelerate in the [Platform Console](https://pris.ly/pdp) in two ways: ### 1. When enabling Accelerate for your project environment: 1. Specify your database connection string and connection pool region. 2. Enable static IP by toggling the **Static IP** switch in the **Network restrictions** section. 3. Click on the **Enable Accelerate** button. ### 2. For projects already using Accelerate: 1. Navigate to the Accelerate **Settings** tab in the project environment. 2. Enable static IP by toggling the **Static IP** switch in the **Network restrictions** section. Enabling static IP for Accelerate will provide you with a list of static IPv4 and IPv6 addresses. Once you have these addresses, configure your database firewall to allow incoming connections only from these IPs and any other trusted IPs that need access to your database. :::note Since you cannot enable static IP for an existing Accelerate-enabled environment, we recommend opting for static IP when enabling Accelerate in a new environment. Use the same database URL as your existing Accelerate environment to instantly access static IP support for Accelerate. ::: --- # API Reference URL: https://www.prisma.io/docs/accelerate/api-reference The Accelerate API reference documentation is based on the following schema: ```prisma model User { id Int @id @default(autoincrement()) name String? email String @unique } ``` All example are based on the `User` model. ## `cacheStrategy` With the Accelerate extension for Prisma Client, you can use the `cacheStrategy` parameter for model queries and use the [`ttl`](/accelerate/caching#time-to-live-ttl) and [`swr`](/accelerate/caching#stale-while-revalidate-swr) parameters to define a cache strategy for Accelerate. The Accelerate extension requires that you install Prisma Client version `4.10.0`. ### Options The `cacheStrategy` parameter takes an option with the following keys: | Option | Example | Type | Required | Description | | ------ | ------- | ----- | -------- | ------------------------------------------- | | `swr` | `60` | `Int` | No | The stale-while-revalidate time in seconds. | | `ttl` | `60` | `Int` | No | The time-to-live time in seconds. | | `tags` | `["user"]` | `String[]` | No | The `tag` serves as a variable to control the invalidation of specific queries within your application. It is an optional array of strings to [invalidate](/accelerate/api-reference#accelerateinvalidate) the cache, with each tag containing only alphanumeric characters and underscores, and a maximum length of 64 characters. | ### Examples Add a caching strategy to the query, defining a 60-second stale-while-revalidate (SWR) value, a 60-second time-to-live (TTL) value, and a cache tag of `"emails_with_alice"`: ```ts highlight=7:11;normal await prisma.user.findMany({ where: { email: { contains: "alice@prisma.io", }, }, // highlight-start cacheStrategy: { swr: 60, ttl: 60, tags: ["emails_with_alice"], }, // highlight-end }); ``` ### Supported Prisma Client operations The following is a list of all read query operations that support `cacheStrategy`: - [`findUnique()`](/orm/reference/prisma-client-reference#findunique) - [`findUniqueOrThrow()`](/orm/reference/prisma-client-reference#finduniqueorthrow) - [`findFirst()`](/orm/reference/prisma-client-reference#findfirst) - [`findFirstOrThrow()`](/orm/reference/prisma-client-reference#findfirstorthrow) - [`findMany()`](/orm/reference/prisma-client-reference#findmany) - [`count()`](/orm/reference/prisma-client-reference#count) - [`aggregate()`](/orm/reference/prisma-client-reference#aggregate) - [`groupBy()`](/orm/reference/prisma-client-reference#groupby) The `cacheStrategy` parameter is not supported on any write operations, such as `create()`. ## `withAccelerateInfo` Any query that supports the `cacheStrategy` can append `withAccelerateInfo()` to wrap the response data and include additional information about the Accelerate response. To retrieve the status of the response, use: ```ts const { data, info } = await prisma.user .count({ cacheStrategy: { ttl: 60, swr: 600 }, where: { myField: 'value' }, }) .withAccelerateInfo() console.dir(info) ``` Notice the `info` property of the response object. This is where the request information is stored. ### Return type The `info` object is of type `AccelerateInfo` and follows the interface below: ```ts interface AccelerateInfo { cacheStatus: 'ttl' | 'swr' | 'miss' | 'none' lastModified: Date region: string requestId: string signature: string } ``` | Property | Type | Description | | -------------- | ------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cacheStatus` | `"ttl" \| "swr" \| "miss" \| "none" ` | The cache status of the response.
  • `ttl` indicates a cache hit within the `ttl` duration and no database query was executed
  • `swr` indicates a cache hit within the `swr` duration and the data is being refreshed by Accelerate in the background
  • `miss` indicates that both `ttl` and `swr` have expired and the database query was executed by the request
  • `none` indicates that no cache strategy was specified and the database query was executed by the request
| | `lastModified` | `Date` | The date the response was last refreshed. | | `region` | `String` | The data center region that received the request. | | `requestId` | `String` | Unique identifier of the request. Useful for troubleshooting. | | `signature` | `String` | The unique signature of the Prisma operation. | ## `$accelerate.invalidate` You can invalidate the cache using the [`$accelerate.invalidate` API](/accelerate/). :::note To invalidate cached query results on-demand, a paid plan is required. Each plan has specific limits on the number of cache tag-based invalidations allowed per day, though there are no limits on calling the `$accelerate.invalidate` API itself. See our [pricing for more details](https://www.prisma.io/pricing#accelerate). ::: ### Example To invalidate the query below: ```ts await prisma.user.findMany({ where: { email: { contains: "alice@prisma.io", }, }, cacheStrategy: { swr: 60, ttl: 60, // highlight-start tags: ["emails_with_alice"], // highlight-end }, }); ``` You need to provide the cache tag in the `$accelerate.invalidate` API: ```ts try { // highlight-start await prisma.$accelerate.invalidate({ tags: ["emails_with_alice"], }); // highlight-end } catch (e) { if (e instanceof Prisma.PrismaClientKnownRequestError) { // The .code property can be accessed in a type-safe manner if (e.code === "P6003") { console.log( "The cache invalidation rate limit has been reached. Please try again later." ); } } throw e; } ``` :::note You can invalidate up to 5 tags per call. ::: ## `$accelerate.invalidateAll` You can invalidate the entire cache using the `$accelerate.invalidateAll` API. ### Example To invalidate the query below: ```ts await prisma.user.findMany({ where: { email: { contains: "alice@prisma.io", }, }, cacheStrategy: { swr: 60, ttl: 60, // highlight-start tags: ["emails_with_alice"], // highlight-end }, }); ``` Just call the `$accelerate.invalidateAll` API: ```ts try { // highlight-start await prisma.$accelerate.invalidateAll(); // highlight-end } catch (e) { if (e instanceof Prisma.PrismaClientKnownRequestError) { if (e.code === "P6003") { console.log( "The cache invalidation rate limit has been reached. Please try again later." ); } } throw e; } ``` ### Why use `$accelerate.invalidateAll`? This method offers better editor support (e.g. IntelliSense) than alternatives like `invalidate("all")`. :::warning This clears cache for the entire environment—use with care. ::: ## Errors Prisma Accelerate-related errors start with `P6xxx`. You can find the full error code reference for Prisma Accelerate [here](/orm/reference/error-reference#prisma-accelerate). --- # Known limitations URL: https://www.prisma.io/docs/accelerate/known-limitations Below are descriptions of known limitations when using Accelerate. If you encounter any additional ones, please share them with us via [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=intro_text). ## Cannot cache raw queries At the moment, it is not possible to cache the responses of [raw queries](/orm/prisma-client/using-raw-sql/raw-queries). ## Not compatible with the fluent API Client Extensions (which are used in Accelerate) currently do not correctly forward the [fluent API](/orm/prisma-client/queries/relation-queries#fluent-api) types. We hope to get a fix into Client Extensions soon. ## Not compatible with extremely heavy or long-running queries Accelerate is designed to work with high-performance, low-latency queries. It is not intended for use with extremely heavy or long-running queries that may cause performance issues or resource contention. While limits are configurable, we recommend optimizing your queries to ensure they fit within the recommended guidelines. For queries that cannot be optimized or pared down, we recommend one of two solutions: 1. **Use the read replica extension**: The Prisma ORM [read replica extension](https://www.npmjs.com/package/@prisma/extension-read-replicas) allows you to set up two different connections: a `primary` and a `replica`. You can set up your Accelerate connection as the `primary` and then a direct connection as the `replica`. Any queries that are resource-intensive or long-running can then be routed to the `replica`, while the `primary` (your Accelerate connection) will handle normal queries. **Please note** that this solution requires you to both set up a direct connection and requires the full generated Prisma Client (i.e. without `--no-engine`). 2. **Separate analytics queries**: Our preferred solution is to separate your analytics queries into a separate application. This separate application can then use a direct connection so that it can run heavy queries without impacting the performance or cost of your Accelerate-powered application. If you have a use case that requires running extremely heavy or long-running queries and Prisma Accelerate, please reach out to us. ## Not compatible with direct IPv4 addresses in MongoDB connection strings Accelerate does not support direct IPv4 addresses in MongoDB connection strings. When an IPv4 address is provided, Accelerate converts it to an IPv6 format to route through its NAT gateway. This conversion may cause the connection string to be considered invalid due to the formatting of the port value. **Workaround**: To resolve this issue, create a DNS record that points to your IPv4 address and use that DNS record in your connection string instead of the direct IP. ### Example - **IPv4 connection string** (not supported): `mongodb://user:password@192.168.1.100:27017/db_name` - **DNS record connection string** (supported): `mongodb://user:password@my-database.example.com:27017/db_name` For additional details on Accelerate’s IPv6-first design, refer to our [blog post](https://www.prisma.io/blog/accelerate-ipv6-first). --- # Evaluating URL: https://www.prisma.io/docs/accelerate/evaluating Prisma Accelerate optimizes database interactions through advanced connection pooling and global edge caching. Its connection pooler is available in 16 regions and helps applications load-balance and scale database requests based on demand. Considering the information above, we recommend evaluating Accelerate with high volume to see it perform under load. ## How Accelerate's connection pool optimizes performance under load Prisma Accelerate employs a dynamic, serverless connection pooling infrastructure. When a request is made, a connection pool is quickly provisioned for the project in the region assigned while configuring Prisma Accelerate. This connection pool remains active, serving many additional requests while reusing established database connections. The connection pool will disconnect after a period of inactivity, so it’s important to evaluate Prisma Accelerate with a consistent stream of traffic. **Key Benefits:** - **Optimized Query Performance:** The serverless connection pooler adapts to the query load, ensuring the database connections are managed efficiently during peak demand. > Prisma Accelerate’s connection pooler cannot improve the performance of queries in the database. In scenarios where query performance is an issue, we recommend optimizing the Prisma query, applying indexes, or utilizing Accelerate’s edge caching. - **Maximize Connection Reuse:** Executing a consistent volume of queries helps maintain active instances of Accelerate connection poolers. This increases connection reuse, ensuring faster response times for subsequent queries. By understanding and harnessing this mechanism, you can ensure that your database queries perform consistently and efficiently at scale. ## Evaluating Prisma Accelerate connection pooling performance Below you will find an example of how to evaluate Prisma Accelerate using a sample model: ```prisma model Notes { id Int @id @default(autoincrement()) title String createdAt DateTime @default(now()) updatedAt DateTime? @updatedAt } ``` ```typescript import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' const prisma = new PrismaClient().$extends(withAccelerate()) function calculateStatistics(numbers: number[]): { average: number p50: number p75: number p99: number } { if (numbers.length === 0) { throw new Error('The input array is empty.') } // Sort the array in ascending order numbers.sort((a, b) => a - b) const sum = numbers.reduce((acc, num) => acc + num, 0) const count = numbers.length const average = sum / count const p50 = getPercentile(numbers, 50) const p75 = getPercentile(numbers, 75) const p99 = getPercentile(numbers, 99) return { average, p50, p75, p99 } } function getPercentile(numbers: number[], percentile: number): number { if (percentile <= 0 || percentile >= 100) { throw new Error('Percentile must be between 0 and 100.') } const index = (percentile / 100) * (numbers.length - 1) if (Number.isInteger(index)) { // If the index is an integer, return the corresponding value return numbers[index] } else { // If the index is not an integer, interpolate between two adjacent values const lowerIndex = Math.floor(index) const upperIndex = Math.ceil(index) const lowerValue = numbers[lowerIndex] const upperValue = numbers[upperIndex] const interpolationFactor = index - lowerIndex return lowerValue + (upperValue - lowerValue) * interpolationFactor } } async function main() { const timings = [] // fire a query before going to the loop await prisma.notes.findMany({ take: 20, }) // we recommend evaluationg Prisma Accelerate with a large loop const LOOP_LENGTH = 10000 for (let i = 0; i < LOOP_LENGTH; i++) { const start = Date.now() await prisma.notes.findMany({ take: 20, }) timings.push(Date.now() - start) } const statistics = calculateStatistics(timings) console.log('Average:', statistics.average) console.log('P50:', statistics.p50) console.log('P75:', statistics.p75) console.log('P99:', statistics.p99) } main() .then(async () => { await prisma.$disconnect() }) .catch((e) => { await prisma.$disconnect() process.exit(1) }) ``` ## Evaluating Prisma Accelerate caching performance Prisma Accelerate’s edge cache is also optimized for a high volume of queries. The cache automatically optimizes for repeated queries. As a result, the cache hit rate will increase as the query frequency does. Adding a query result to the cache is also non-blocking, so a short burst of queries might not utilize the cache or a sustained load. To evaluate Accelerate’s edge caching, you can modify the above script with the below: ```typescript import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' const prisma = new PrismaClient().$extends(withAccelerate()) function calculateStatistics(numbers: number[]): { average: number p50: number p75: number p99: number } { if (numbers.length === 0) { throw new Error('The input array is empty.') } // Sort the array in ascending order numbers.sort((a, b) => a - b) const sum = numbers.reduce((acc, num) => acc + num, 0) const count = numbers.length const average = sum / count const p50 = getPercentile(numbers, 50) const p75 = getPercentile(numbers, 75) const p99 = getPercentile(numbers, 99) return { average, p50, p75, p99 } } function getPercentile(numbers: number[], percentile: number): number { if (percentile <= 0 || percentile >= 100) { throw new Error('Percentile must be between 0 and 100.') } const index = (percentile / 100) * (numbers.length - 1) if (Number.isInteger(index)) { // If the index is an integer, return the corresponding value return numbers[index] } else { // If the index is not an integer, interpolate between two adjacent values const lowerIndex = Math.floor(index) const upperIndex = Math.ceil(index) const lowerValue = numbers[lowerIndex] const upperValue = numbers[upperIndex] const interpolationFactor = index - lowerIndex return lowerValue + (upperValue - lowerValue) * interpolationFactor } } async function main() { const timings = [] // fire a query before going to the loop await prisma.notes.findMany({ take: 20, cacheStrategy: { ttl: 30, }, }) // we recommend evaluating Prisma Accelerate with a large loop const LOOP_LENGTH = 10000 for (let i = 0; i < LOOP_LENGTH; i++) { const start = Date.now() await prisma.notes.findMany({ take: 20, cacheStrategy: { ttl: 30, }, }) timings.push(Date.now() - start) } const statistics = calculateStatistics(timings) console.log('Average:', statistics.average) console.log('P50:', statistics.p50) console.log('P75:', statistics.p75) console.log('P99:', statistics.p99) } main() .then(async () => { await prisma.$disconnect() }) .catch((e) => { await prisma.$disconnect() process.exit(1) }) ``` --- # Local development URL: https://www.prisma.io/docs/accelerate/local-development Prisma Accelerate efficiently scales production traffic with integrated connection pooling and a global database cache. In development environments, you may want to use a local database to minimize expenses. Furthermore, you may consider extending Prisma Client with the Accelerate client extension once so that you can use a local database in development and a hosted database with Accelerate’s connection pooling and caching enabled. This eliminates the need for conditional logic to switch clients between development and production. This guide will explain how to use Prisma Accelerate client extension in a development environment with a local database. ## Using Prisma Accelerate client extension in development and production
![Using Prisma Accelerate client extension in development](/img/accelerate/accelerate-in-dev.png) Accelerate does not work with a local database. However, in a development environment, you can still use Prisma Client with the Accelerate client extension. This setup will not provide Accelerate's connection pooling and caching features. The following steps outline how to use Prisma ORM and Prisma Accelerate with a local PostgreSQL database. 1. Update the `DATABASE_URL` environment variable with your local database's connection string: ```.env DATABASE_URL="postgres://username:password@127.0.0.1:5432/localdb" ``` 2. Generate a Prisma Client: ```bash npx prisma generate ``` > Note: The `--no-engine` flag should only be used in preview and production environments. The command generates Prisma Client artifacts without a [Query Engine](/orm/more/under-the-hood/engines) file, which requires an Accelerate connection string. 3. Set up Prisma Client with the Accelerate client extension: ```typescript import { PrismaClient } from '@prisma/client' import { withAccelerate } from '@prisma/extension-accelerate' const prisma = new PrismaClient().$extends(withAccelerate()) ``` > The extended instance of Prisma Client will use the local database. Hence, Prisma Accelerate will not be used in your development environment to respond to your Prisma Client queries. ![Using Prisma Accelerate client extension in production](/img/accelerate/accelerate-in-prod.png) If an Accelerate connection string is used as the `DATABASE_URL` environment variable, Prisma Client will route your queries through Accelerate. ## Using Prisma Accelerate locally in an edge function When using an edge function, e.g., [Vercel's edge runtime](https://vercel.com/docs/functions/runtimes/edge-runtime), for your development environment, update your Prisma Client import as follows: ```typescript import { PrismaClient } from '@prisma/client/edge' ``` Generally, edge function environments lack native support for existing APIs enabling TCP-based database connections. Prisma Accelerate provides a connection string that allows querying your database over HTTP, a protocol supported in all edge runtimes. --- # FAQ URL: https://www.prisma.io/docs/accelerate/faq ## When should I enable static IP for Prisma Accelerate? Enable static IP for Accelerate when your security setup requires IP allowlisting or if you're implementing firewalls that only permit access from trusted IPs, ensuring controlled and secure database connections. ![Result of enabling static IP Accelerate with a database using IP allowlisting](/img/accelerate/result-of-adding-static-ip-to-accelerate.png) Learn more on [how to enable static IP for Accelerate in the Platform Console](/accelerate/static-ip). :::info **What is a static IP?** A static IP address is an IPv4 or an IPv6 address that is fixed. Unlike dynamic IP addresses, which can change unpredictably, traffic from static IP addresses can be easily identified. ![What is a static IP](/img/accelerate/static-ip.png) ::: > ℹ️ To enable static IP support for Accelerate within your existing or new project environment, your workspace will need to be on our **Pro** or **Business** plans. Take a look at the [pricing page](https://www.prisma.io/pricing#accelerate) for more information. ## Why do I sometimes see unexpected cache behavior? Accelerate's cache performs best when it observes a higher load from a project. Many cache operations, such as committing data to cache and refreshing stale data, happen asynchronously. When benchmarking Accelerate, we recommend doing so with loops or a load testing approach. This will mimic higher load scenarios better and reduce outliers from low frequency operations. Prisma operations are sent to Accelerate over HTTP. As a result, the first request to Accelerate must establish an HTTP handshake and may have additional latency as a result. We're exploring ways to reduce this initial request latency in the future. ## What is the pricing of Accelerate? You can find more details on our [Accelerate pricing page](https://www.prisma.io/pricing) ## VS Code does not recognize the `$extends` method If you add the Prisma Client extension for Accelerate to an existing project that is currently open in VS Code, the editor might not immediately recognize the `$extends` method. This might be an issue with the TypeScript server not yet recognizing the regenerated Prisma Client. To resolve this, you need to restart TypeScript. 1. In VS Code, open the Command Palette. You can do so when you press F1 or select **View** > **Command Palette**. 2. Enter `typescript` and select and run the **TypeScript: Restart TS server** command. VS Code should now recognize the `$extends` method. ## What regions are Accelerate's cache nodes available in? Accelerate runs on Cloudflare's network and cache hits are served from Cloudflare's 300+ locations. You can find the regions where Accelerate's cache nodes are available here: [https://www.cloudflare.com/network/](https://www.cloudflare.com/network/). ## What regions is Accelerate's connection pool available in? When no cache strategy is specified or in the event of a cache miss, the Prisma Client query is routed through Accelerate's connection pool. Currently, queries can be routed through any chosen region among the 16 available locations. Currently, the list of available regions are: - Asia Pacific, Mumbai (`ap-south-1`) - Asia Pacific, Seoul (`ap-northeast-2`) - Asia Pacific, Singapore (`ap-southeast-1`) - Asia Pacific, Sydney (`ap-southeast-2`) - Asia Pacific, Tokyo (`ap-northeast-1`) - Canada, Central (`ca-central-1`) - Europe, Frankfurt (`eu-central-1`) - Europe, Ireland (`eu-west-1`) - Europe, London (`eu-west-2`) - Europe, Paris (`eu-west-3`) - Europe, Stockholm (`eu-north-1`) - South America, Sao Paulo (`sa-east-1`) - US East, N. Virginia (`us-east-1`) - US East, Ohio (`us-east-2`) - US West, N. California (`us-west-1`) - US West, Oregon (`us-west-2`) You can also view the available regions when you're about to set up Accelerate or by visiting the **Settings** tab for Accelerate under the **Region** section in the Prisma Cloud Platform [dashboard](https://pris.ly/pdp). ## How does Accelerate know what region to fetch the cache from? Under the hood, Accelerate uses Cloudflare, which uses [Anycast](https://www.cloudflare.com/learning/cdn/glossary/anycast-network/) for network addressing and routing. An incoming request will be routed to the nearest data center or "node" in their network that has the capacity to process the request efficiently. To learn more about how this works, we recommend looking into [Anycast](https://www.cloudflare.com/learning/cdn/glossary/anycast-network/). ## How can I invalidate a cache on Accelerate? You can invalidate the cache on-demand via the [`$accelerate.invalidate` API](/accelerate/api-reference#accelerateinvalidate) if you're on a [paid plan](https://www.prisma.io/pricing#accelerate), or you can invalidate your entire cache, on a project level, a maximum of five times a day. This limit is set based on [your plan](https://www.prisma.io/pricing#accelerate). You can manage this via the Accelerate configuration page. ## What is Accelerate's consistency model? Accelerate does not have a consistency model. It is not a distributed system where nodes need to reach a consensus (because data is only stored in the cache node(s) closest to the user). However, the data cached in Accelerate's cache nodes doesn't propagate to other nodes, so Accelerate by design doesn't need a consistency model. Accelerate implements a [read-through caching strategy](https://www.prisma.io/dataguide/managing-databases/introduction-database-caching#read-through) particularly suitable for read-heavy workloads. The freshness of the data served by the cache depends on the cache strategy defined in your query. Refer to [this section](/accelerate/caching#selecting-a-cache-strategy) for more information on selecting the right cache strategy for your query. ## How is Accelerate different from other caching tools, such as Redis? - Accelerate is a _specialized_ cache that allows you to optimize data access in code at the query level with a cache strategy. On the other hand, tools such as Redis and Memcached are _general-purpose_ caches designed to be adaptable and flexible. - Accelerate is a managed service that reduces the time, risk, and engineering effort of building and maintaining a cache service. - By default, Accelerate is globally distributed, reducing the latency of your queries. Other cache tools would require additional configuration to make them available globally. ## When should I not use Accelerate's caching features? Accelerate is a global data cache and connection pool that allows you to optimize data access in code at the query level. While caching with Accelerate can greatly boost the performance of your app, it may not always the best choice for your use case. Accelerate's global cache feature may not be a good fit for your app if: - Your app is exclusively used within a specific region and both your application server and database are situated in that same region on the same network. For example, database queries will likely be much faster if your application server and database are in the same region and network. However, If your application server is in different regions or networks from your database, Accelerate will speed up your queries because the data will be cached in the closest data center to your application. - You _only_ need a general-purpose cache. Accelerate is a connection pooler and a _specialized cache_ that only caches your database query responses in code. A general-purpose cache, such as Redis, would allow you to cache data from multiple sources, such as external APIs, which Accelerate currently doesn't support. If general-purpose caching interests you, please share your feedback with us via our [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=inline_text). - Your application data _always_ needs to be up-to-date on retrieval, making it difficult to establish a reasonable cache strategy. Even without using Accelerate's global cache, you can still greatly benefit from Accelerate by using its connection pool, especially in serverless or edge functions, where it is difficult to manage and scale database connections. You can learn more about the serverless challenge [here](/orm/prisma-client/setup-and-configuration/databases-connections#the-serverless-challenge). ## Can I use Accelerate with other ORMs/query builders/drivers? No. We currently do not have any plans for supporting other ORMs/query builders or drivers. However, if you're interested in support for other libraries, feel free to reach out and let us know in our [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=inline_text) community in the `#help-and-questions` channel. ## What is the maximum allowed value for the `ttl` parameter when configuring `cacheStrategy`? The [Time-to-live](/accelerate/caching#time-to-live-ttl) (`ttl`) parameter can be set for up to a _year_. However, it's important to note that items within the cache may be evicted if they are not frequently accessed. Based on our experimentation, we’ve seen cache items persist for around 18 hours. While items may remain in the cache for an extended period if they are actively accessed, there is no guarantee. > **Note**: Even frequently accessed items may occasionally be evicted from the cache. It's unlikely for an item to survive for up to or longer than a month, regardless of its activity level. ## Why doesn’t Accelerate fall back to the direct connection string during a service disruption? In the rare event of a service disruption, falling back to a direct connection would bypass the connection pool. This could potentially deplete the database's available connections and cause other issues on the database level. If there is a service disruption, it's recommended to verify on the [status page](https://pris.ly/data-platform-status). You can reach out to one of Prisma's [support channels](/platform/support) for assistance. > **Note:** Additionally, it's worth noting that some edge function runtime environments may not support direct connections with Prisma ORM. For further details, refer to our [Edge functions documentation](/orm/prisma-client/deployment/edge/overview). ## Are each of the queries within an interactive transaction counted separately for billing? Yes, [interactive transactions](/orm/prisma-client/queries/transactions#interactive-transactions) are billed based on the individual operations within the transaction. There is no charge for the start, commit, or rollback of the transaction itself. For example, in the following query, there are two billable queries: ```ts await prisma.$transaction(async (tx) => { await tx.user.deleteMany({ where: { name: 'John Doe' } }); await tx.user.createMany({ data }); }); ``` However, when using the [`$transaction` API for sequential client operations](/orm/prisma-client/queries/transactions#sequential-prisma-client-operations), regardless of the number of queries within the array, it counts as only one billable query. For example: ```ts await prisma.$transaction([ prisma.user.deleteMany({ where: { name: 'John Doe' } }), prisma.user.createMany({ data }), ]); ``` If you don't need [interactive transactions](/orm/prisma-client/queries/transactions#interactive-transactions), you can save costs and improve performance by using [sequential operations transactions](/orm/prisma-client/queries/transactions#sequential-prisma-client-operations). Sequential operations transactions perform better on Accelerate because they execute in one round-trip to the database, while interactive transactions require separate round-trips for start, commit, and each individual operation on the transaction. ## Can I increase my Accelerate query duration and response size limits? Yes, you can increase your Accelerate limits based on your subscription plan. Here are the configurable limits: | Limit | Starter | Pro Plan | Business Plan | |--------------------------------|-------------------|-------------------|-------------------| | **Query timeout** | Up to 10 seconds | Up to 20 seconds | Up to 60 seconds | | **Interactive transactions timeout** | Up to 15 seconds | Up to 30 seconds | Up to 90 seconds | | **Response size** | Up to 5 MB | Up to 10 MB | Up to 20 MB | Check the [pricing page](https://www.prisma.io/pricing#accelerate) for more details on the available plans and their corresponding limits. :::warning While you can increase these limits based on your subscription plan, it's *still* recommended to optimize your database operations. [Learn more in our troubleshooting guide.](/accelerate/troubleshoot) ::: ## How long does it take to invalidate a cache query result? As the cache needs to be cleared globally, it is difficult to provide a specific time frame. However, the cached data is eventually consistent and typically propagates to all PoPs within a few seconds. In very rare cases, it may take longer. Here is a [demo app](https://pris.ly/test-cache-invalidation) to test the time it takes to invalidate a cache query result. ## What is the difference between **Invalidate** and **Revalidate**? **Invalidate**: The cache entry is deleted, and new data will be fetched on the next request, causing a cache miss. This removes stale data but may lead to slower responses until the cache is repopulated. **Revalidate**: The cache entry is updated proactively, ensuring the next request uses fresh data from the cache. This keeps the cache valid and maintains faster response times by avoiding cache misses. ## What is on-demand cache invalidation? [On-demand cache invalidation](/accelerate/caching#on-demand-cache-invalidation) lets applications instantly update specific cached data when it changes, instead of waiting for regular cache refresh cycles. This keeps information accurate and up-to-date for users. ## When should I use the cache invalidate API? The [cache invalidate API](/accelerate/caching#on-demand-cache-invalidation) is essential when data consistency cannot wait for the cache’s standard expiration or revalidation. Key use cases include: - **Content updates**: When critical changes occur, such as edits to a published article, product updates, or profile modifications, that need to be visible immediately. - **Inventory management**: In real-time applications, like inventory or booking systems, where stock levels, availability, or reservation statuses must reflect the latest information. - **High-priority data**: For time-sensitive data, like breaking news or urgent notifications, where it’s essential for users to see the most current information right away. Using on-demand cache invalidation in these scenarios helps keep only the necessary data refreshed, preserving system performance while ensuring accurate, up-to-date information for users. ## How does Accelerate count queries for billing? Accelerate counts queries at the Prisma Client invocation level. A single Prisma query may translate into multiple SQL statements under the hood, but it will only count as one query for billing purposes. This ensures straightforward, predictable billing that reflects the Prisma Client usage rather than the complexity of the underlying SQL operations. Queries are counted regardless of whether they are served from the cache or the database. Even if a query is retrieved from the cache, it still counts toward your query limit. ## How do I switch from GitHub login to email and password login? If you previously signed up using GitHub and want to switch to email and password login, follow these steps: ### 1. Verify Your GitHub Email Address - Check the primary email address associated with your GitHub account (e.g., from your GitHub profile or notification settings). ### 2. Create a New Email/Password Account - Go to the email/password sign-up page. - Use the **same email address** linked to your GitHub account to create the new account. - Our system will automatically connect your new email/password account to your existing data. ### 3. Test Your Login - Log out and try logging in with your email and the password you just created. > **Note**: If you encounter any issues, please contact our support team for help linking your accounts. --- # Troubleshooting URL: https://www.prisma.io/docs/accelerate/troubleshoot When working with Prisma Accelerate, you may encounter errors often highlighted by specific error codes during development and operations. It is important to understand the meaning of these errors, why they occur, and how to resolve them in order to ensure the smooth operation of your applications. This guide aims to provide insights and steps to troubleshoot specific error codes encountered with Prisma Accelerate. ## [`P6009`](/orm/reference/error-reference#p6009-responsesizelimitexceeded) (`ResponseSizeLimitExceeded`) This error is triggered when the response size from a database query exceeds [the configured query response size limit](/accelerate/connection-pooling#response-size-limit). We've implemented this restriction to safeguard your application performance, as retrieving data over 5MB can significantly slow down your application due to multiple network layers. Typically, transmitting more than 5MB of data is common when conducting ETL (Extract, Transform, Load) operations. However, for other scenarios such as transactional queries, real-time data fetching for user interfaces, bulk data updates, or aggregating large datasets for analytics outside of ETL contexts, it should generally be avoided. These use cases, while essential, can often be optimized to work within [the configured query response size limit](/accelerate/connection-pooling#response-size-limit), ensuring smoother performance and a better user experience. ### Possible causes for [`P6009`](/orm/reference/error-reference#p6009-responsesizelimitexceeded) #### Transmitting images/files in response This error may arise if images or files stored within your table are being fetched, resulting in a large response size. Storing assets directly in the database is generally discouraged because it significantly impacts database performance and scalability. In addition to performance, it makes database backups slow and significantly increases the cost of storing routine backups. **Suggested solution:** Configure the [query response size limit](/accelerate/connection-pooling#response-size-limit) to be larger. If the limit is still exceeded, consider storing the image or file in a BLOB store like [Cloudflare R2](https://developers.cloudflare.com/r2/), [AWS S3](https://aws.amazon.com/pm/serv-s3/), or [Cloudinary](https://cloudinary.com/). These services allow you to store assets optimally and return a URL for access. Instead of storing the asset directly in the database, store the URL, which will substantially reduce the response size. #### Over-fetching of data In certain cases, a large number of records or fields are unintentionally fetched, which results in exceeding [the configured query response size limit](/accelerate/connection-pooling#response-size-limit). This could happen when the [`where`](/orm/reference/prisma-client-reference#where) clause in the query is incorrect or entirely missing. **Suggested solution:** Configure the [query response size limit](/accelerate/connection-pooling#response-size-limit) to be larger. If the limit is still exceeded, double-check that the `where` clause is filtering data as expected. To prevent fetching too many records, consider using [pagination](/orm/prisma-client/queries/pagination). Additionally, use the [`select`](/orm/reference/prisma-client-reference#select) clause to return only the necessary fields, reducing the response size. #### Fetching a large volume of data In many data processing workflows, especially those involving ETL (Extract-Transform-Load) processes or scheduled CRON jobs, there's a need to extract large amounts of data from data sources (like databases, APIs, or file systems) for analysis, reporting, or further processing. If you are running an ETL/CRON workload that fetches a huge chunk of data for analytical processing then you might run into this limit. **Suggested solution:** Configure the [query response size limit](/accelerate/connection-pooling#response-size-limit) to be larger. If the limit is exceeded, consider splitting your query into batches. This approach ensures that each batch fetches only a portion of the data, preventing you from exceeding the size limit for a single operation. ## [`P6004`](/orm/reference/error-reference#p6004-querytimeout) (`QueryTimeout`) This error occurs when a database query fails to return a response within [the configured query timeout limit](/accelerate/connection-pooling#query-timeout-limit). The query timeout limit includes the duration of waiting for a connection from the pool, network latency to the database, and the execution time of the query itself. We enforce this limit to prevent unintentional long-running queries that can overload system resources. > The time for Accelerate's cross-region networking is excluded from [the configured query timeout limit](/accelerate/connection-pooling#query-timeout-limit) limit. ### Possible causes for [`P6004`](/orm/reference/error-reference#p6004-querytimeout) This error could be caused by numerous reasons. Some of the prominent ones are: #### High traffic and insufficient connections If the application is receiving very high traffic and there are not a sufficient number of connections available to the database, then the queries would need to wait for a connection to become available. This situation can lead to queries waiting longer than [the configured query timeout limit](/accelerate/connection-pooling#query-timeout-limit) for a connection, ultimately triggering a timeout error if they do not get serviced within this duration. **Suggested solution**: Review and possibly increase the `connection_limit` specified in the connection string parameter when setting up Accelerate in a platform environment ([reference](/accelerate/connection-pooling#configuring-the-connection-pool-size)). This limit should align with your database's maximum number of connections. By default, the connection limit is set to 10 unless a different `connection_limit` is specified in your database connection string. #### Long-running queries Queries may be slow to respond, hitting [the configured query timeout limit](/accelerate/connection-pooling#query-timeout-limit) even when connections are available. This could happen if a very large amount of data is being fetched in a single query or if appropriate indexes are missing from the table. **Suggested solution**: Configure the [query timeout limit](/accelerate/connection-pooling#query-timeout-limit) to be larger. If the limit is exceeded, identify the slow-running queries and fetch only the necessary data. Use the `select` clause to retrieve specific fields and avoid fetching unnecessary data. Additionally, consider adding appropriate indexes to improve query efficiency. You might also isolate long-running queries into separate environments to prevent them from affecting transactional queries. #### Database resource contention A common yet challenging issue is when other services operating on the same database perform heavy analytics or data processing tasks, significantly consuming database resources. These operations can monopolize database connections and processing power, leading to a scenario where even simple queries cannot be executed in a timely manner. This "busy" or "noisy" database environment can cause queries that are typically fast to run slowly or even timeout, particularly during periods of high activity from other services. Users often rely on CPU and memory usage metrics to gauge database load, which can be misleading. While these are important indicators, they might not fully represent the database's operational state. Direct metrics like the number of reads, writes, and wait times offer a clearer view of the database's performance and should be monitored closely. A noticeable degradation in these metrics, especially in the absence of changes to the queries or data model, suggests that external pressures are affecting database performance. **Suggested solution**: If normally quick queries are intermittently slow or timing out without any modifications to them, it's probable that competing queries are exerting pressure on the same database tables. To diagnose this, adopt monitoring tools or leverage your database's inherent capabilities to observe reads, writes, and wait times. Such monitoring will unveil activity patterns or spikes that align with the observed performance dips. Moreover, it's crucial to periodically scrutinize and refine essential queries and verify that tables are properly indexed. This proactive approach minimizes the vulnerability of these queries to slowdowns caused by competing workloads. ### Considerations for [`P6009`](/orm/reference/error-reference#p6009-responsesizelimitexceeded) and [`P6004`](/orm/reference/error-reference#p6004-querytimeout) errors For runtimes that support Prisma ORM natively, you could consider creating two `PrismaClient` Instances. One with the Accelerate connection string (prefixed with `prisma://`) and the other one with the direct database connection string (prefixed with `postgres://`, `mysql://` etc). The main idea behind this approach is to bypass Accelerate for certain specific queries. However, please note that the available connections would be split between both of your `PrismaClient` Instances. It's crucial to understand the implications of managing multiple instances, particularly in regards to direct database connections. Utilizing a `PrismaClient` instance with a direct database connection string means that this connection will interact directly with your database. This approach requires careful consideration because the direct connections and those managed by Accelerate share the same underlying database connection pool. This can lead to competition for resources, potentially affecting the performance and availability of your database services. Additionally, direct connections could have a significant impact on your database's performance and availability. Operations that consume a considerable amount of resources could potentially degrade the service for other users or processes that rely on the same database. If your application's runtime environment supports Prisma ORM natively and you're considering this strategy to circumvent P6009 and P6004 errors, you might create two `PrismaClient` instances: 1. An instance using the Accelerate connection string (prefixed with `prisma://`) for general operations. 2. Another instance with the direct database connection string (e.g., prefixed with `postgres://`, `mysql://`, etc.) for specific operations anticipated to exceed [the configured query limit timeout](/accelerate/connection-pooling#query-timeout-limit) or to result in responses larger than [the configured query response size limit](/accelerate/connection-pooling#response-size-limit). ```jsx export const prisma = new PrismaClient({ datasourceUrl: process.env.DIRECT_DB_CONNECTION, }) export const prismaAccelerate = new PrismaClient({ datasourceUrl: process.env.ACCELERATE_CONNECTION, }).$extends(withAccelerate()) ``` This setup allows you to strategically direct certain operations through the direct connection, mitigating the risk of encountering the aforementioned errors. However, this decision should be made with a comprehensive understanding of the potential consequences and an assessment of whether your database infrastructure can support this additional load without compromising overall performance and availability. > Also see [**why doesn’t Accelerate fall back to the direct connection string during a service disruption?**](/accelerate/faq#why-doesnt-accelerate-fall-back-to-the-direct-connection-string-during-a-service-disruption) ## [`P6008`](/orm/reference/error-reference#p6008-connectionerrorenginestarterror) (`ConnectionError|EngineStartError`) This error indicates that Prisma Accelerate cannot establish a connection to your database, potentially due to several reasons. ### Possible causes for [`P6008`](/orm/reference/error-reference#p6008-connectionerrorenginestarterror) #### Database Not Publicly accessible If your database is within a VPC or access is limited to specific IP addresses, you might encounter this error if static IP is not enabled for Accelerate or if the static IPs are not permitted in your database firewall. **Suggested solution:** [Enable static IP for Accelerate](/accelerate/static-ip) and configure your database firewall to allow access from the provided static IP addresses. #### Unreachable Database Host/Port If the database’s server address (hostname) and port are incorrect or unreachable then you may encounter this error. **Suggested solution:** Verify the hostname/port of the database connection string that was provided while creating the Prisma Accelerate project. Additionally, attempt to connect to the database using a Database GUI tool (e.g., [Prisma Studio](https://www.prisma.io/studio), [TablePlus](https://tableplus.com/), or [DataGrip](https://www.jetbrains.com/datagrip/)) for further investigation. #### Incorrect username/password/database name This error can happen when the wrong credentials are provided to Prisma Accelerate, preventing it from establishing a connection to your database. **Suggested solution:** Verify the correctness of your database's username, password, and name in the connection string provided to Prisma Accelerate. Ensure that these credentials match those required by your database. Testing the connection using a direct database GUI tool can also help in confirming if the provided credentials are correct. #### Database taking too long to respond If the database is taking too long to respond to the connection request, Prisma Accelerate may timeout and throw this error. This could happen if the database is not active or is waking up from sleep mode. **Suggested solution:** Verify that the database is active and reachable. If the database is in sleep mode, try to wake it up by sending a request to it using a direct database GUI tool or wake it up using the database's management console. ## [`P5011`](/orm/reference/error-reference#p5011-too-many-requests) (`TooManyRequests`) This error occurs when Prisma Accelerate detects a high volume of requests that surpasses allowable thresholds. It acts as a protective measure to safeguard both Prisma Accelerate and your underlying database from excessive load. ### Possible causes for [`P5011`](/orm/reference/error-reference#p5011-too-many-requests) #### Aggressive retry loops If your application retries queries immediately or with minimal delay, especially after receiving certain errors, the rapid accumulation of requests can surpass the threshold. **Suggested solution:** - Implement an exponential backoff strategy. Rather than retrying immediately or with a fixed delay, gradually increase the delay period after each failed attempt. - This allows the system time to recover and reduces the likelihood of overwhelming Prisma Accelerate and your database. #### Sudden traffic spikes Unpredicted traffic surges (for example, during product launches, flash sales, or viral growth events) can cause the threshold to be met and result into `P5011`. **Suggested solution:** - Consider proactive scaling strategies for both Prisma Accelerate and your database. - Monitor traffic and resource usage. If you anticipate a surge, please contact [support](/platform/support) for capacity planning and potential configuration adjustments. #### Prolonged or planned high workloads Certain processes, such as bulk data imports, ETL operations, or extended CRON jobs, can generate continuous high query volume over time. **Suggested solution:** - Use batching or chunking techniques to break large operations into smaller parts. - Establish throttling or scheduling to distribute the load more evenly. ## Other errors ### Error with MySQL (Aiven): "We were unable to process your request. Please refresh and try again." #### Issue When using an Aiven MySQL connection string that includes the `?ssl-mode=REQUIRED` parameter, you may encounter the following error: ``` We were unable to process your request. Please refresh and try again. ``` #### Cause The `ssl-mode=REQUIRED` parameter is incompatible with Accelerate, which leads to connection issues. #### Suggested solution To resolve this error, remove the `?ssl-mode=REQUIRED` parameter from your MySQL connection string. #### Example - Original connection string: `mysql://username:password@host:port/database?ssl-mode=REQUIRED` - Updated connection string: `mysql://username:password@host:port/database` --- # Feedback URL: https://www.prisma.io/docs/accelerate/feedback You can submit any feedback about Accelerate in our [Discord server](https://pris.ly/discord?utm_source=docs&utm_medium=intro_text). --- # Prisma Accelerate examples URL: https://www.prisma.io/docs/accelerate/examples Here is a list of ready-to-run example projects that demonstrate how to use Prisma Accelerate: | Demo | Description | | ----------------------------------------------- | -------------------------------------------------------------------------- | | [`nextjs-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/nextjs-starter) | A Next.js project using Prisma Accelerate's caching and connection pooling | | [`svelte-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/svelte-starter) | A SvelteKit project using Prisma Accelerate's caching and connection pooling | | [`solidstart-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/solidstart-starter) | A Solidstart project using Prisma Accelerate's caching and connection pooling | | [`remix-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/remix-starter) | A Remix project using Prisma Accelerate's caching and connection pooling | | [`nuxt-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/nuxtjs-starter) | A Nuxt.js project using Prisma Accelerate's caching and connection pooling | | [`astro-starter`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/astro-starter) | An Astro project using Prisma Accelerate's caching and connection pooling | | [`accelerate-hacker-news`](https://github.com/prisma/prisma-examples/tree/latest/accelerate/accelerate-hacker-news) | A simple Hacker News clone built with Prisma Accelerate, demonstrating the use of on-demand cache invalidation | | [`prisma-accelerate-invalidation`](https://github.com/prisma/prisma-accelerate-invalidation) | An app demonstrating how long it takes to invalidate a cached query result using on-demand cache invalidation. | --- # Compare Accelerate URL: https://www.prisma.io/docs/accelerate/compare Prisma Accelerate supports products that serve a global audience, with a global caching system and connection pool that spans multiple regions, providing consistent access to data with low latency no matter where your user (or your database) is located in the world. The managed connection pool is designed to support serverless infrastructure, capable of handling high volumes of connections and adapting to traffic spikes with ease. Explore how Prisma Accelerate compares to other global cache and connection pool solutions on the market, and discover what sets it apart. ## What makes Accelerate unique? Prisma Accelerate is chosen and loved by many for a number of key reasons which make Accelerate unique: - [**Query-Level policies**](/accelerate/compare#accelerate-global-cache): Accelerate is the only solution that offers query-level cache policies, allowing you to control the cache strategy for each query specifically. It is common to have some values that need to be cached for a long time, others that need caching for a short time, and some that should not be cached at all. With Accelerate you can do this, and even set different cache strategies per query. - [**Global by default**](/accelerate/compare#accelerate-global-cache): Accelerate is globally distributed by default. You never need to worry about where a user is located with respect to your database location. - [**Fully managed**](/accelerate/compare#management): You don't need to manage a server or worry about uptime. Accelerate is fully managed for you. - [**Auto-scaling**](/accelerate/compare#performance): Accelerate automatically adjusts resources to match workload demands, providing fast and consistent performance during traffic spikes. ## Accelerate global cache Prisma Accelerate offers a powerful global cache, so you can serve data to your users at the edge — the closest point to where the users are located — no matter where your database is hosted. This not only speeds up the experience for users, but also reduces read load on your database as well by avoiding roundtrips. | | Accelerate | Hyperdrive | Planetscale Boost | | --- | --- | --- | --- | | **Fully Managed** | ✅ | ✅ | ✅ | | **Globally distributed edge infra** | ✅ | ✅ | ✅ | | **Control cache policy from code** | ✅ | ❌ | ❌ | | **Query-level cache policies** | ✅ | ❌ | ❌ | | **Authenticate with API key** | ✅ | ❌ | ❌ | | **Postgres compatible** | ✅ | ✅ | ❌ | | **MySQL compatible** | ✅ | ❌ | ✅ | | **MongoDB compatible** | ✅ | ❌ | ❌ | | **Automatic cache updates** | ❌ | ❌ | ✅ | **Why are these important?** - Since Accelerate extends the Prisma client, you can control caching policies directly from your codebase with just an extra line of code. Integration is seamless. Here is an example using [the stale-while-revalidating caching strategy](/accelerate/caching#stale-while-revalidate-swr): ```jsx await prisma.user.findMany({ cacheStrategy: { swr: 60, }, }); ``` - Query level cache policies are critical for serious applications, so that you can control which queries are cached, and the characteristics of the policy. You may want certain data in your app to be cached for several days, other data to be cached for a just a few minutes, and other data to be not cached at all. This is only possible with Prisma Accelerate. - Authenticating with an API key can be a helpful security measure, allowing you to decouple database credentials from application secrets. Easily rotate API keys as often as you like, without needing any credential changes in your database - Automatic cache updates means that the cache is automatically updated when a change in the database occurs. With Accelerate, you are in control of how the cache is invalidated, using [various caching strategies](/accelerate/caching). ## Accelerate connection pool Prisma Accelerate includes a globally hosted connection pooler, which allows you to handle peak loads without any problem. Using a connection pool is important especially for serverless infrastructure, which by nature is not able to control connection volume to the database on its own. Prisma Accelerate offers a fully managed, globally colocated option, which auto scales to support any workload. ### Management | | Accelerate | pgbouncer | pgcat | Digital Ocean (pgbouncer) | Neon (pgbouncer) | Supavisor | Hyperdrive | | --- | --- | --- | --- | --- | --- | --- | --- | | **Fully managed** | ✅ | ❌ | ❌ | 🟠 | ✅ | ❌ | ✅ | | **Globally distributed** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | | **Integrated with ORM client** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | **Authenticate with API key** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | **Redundancy** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | **Why are these important?** - If you decide to manage a connection pooler yourself (eg. using pgbouncer or pgcat) you will also be responsible for managing its uptime. If the server crashes, your application may be down until you recover it. Accelerate, as a fully managed solution will be recovered for you transparently, in the unlikely case of any infrastructure issue. - The hosted pgbouncer option on Digital Ocean is semi-managed, you will need to set it up in your Digital Ocean account, and ensure it is running smoothly at all times. - Authenticating with an API key can be a helpful security measure, allowing you to decouple database credentials from application secrets. Easily rotate API keys as often as you like, without needing any credential changes in your database - Redundancy is helpful in the unlikely scenario that your connection pool service goes down. With Accelerate, it is automatically and seamlessly handed over to another server and recovered without any interruption. ### Performance | | Accelerate | pgbouncer | pgcat | Digital Ocean (pgbouncer) | Neon (pgbouncer) | Supavisor | Hyperdrive | | --- | --- | --- | --- | --- | --- | --- | --- | | **Auto scaling** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | **Globally distributed** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | | **Optimized queries over HTTP** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | | **Isolated compute** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | **Why are these important?** - Accelerate will automatically scale up and down to suit your application workload, meaning you'll never run out of compute resource. Additionally, this provides important redundancy to protect against any single compute instance failing — in the unlikely event of an instance going down, Accelerate will automatically spawn a new instance. - Cross-region TCP handshakes between the application server and PgBouncer or the database are costly and time-consuming. If connections are reused only at the PgBouncer layer, the TCP handshake and connection setup still consume unnecessary time on every single request, which undermines the efficiency of connection reuse. Prisma Accelerate improves this by leveraging HTTP, which is more efficient for connection management. It reduces the overhead associated with TCP handshakes, resulting in faster, more responsive interactions between your application and the database. - Never worry about 'noisy neighbors' with isolated compute resources. Other customers never impact on your own performance. ### Database Support | | Accelerate | pgbouncer | pgcat | Digital Ocean (pgbouncer) | Neon (pgbouncer) | Supavisor | Hyperdrive | | --- | --- | --- | --- | --- | --- | --- | --- | | **PostgreSQL** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | **MySQL** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | **Planetscale** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | **CockroachDB** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | | **MongoDB** | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | --- import { Bolt, BorderBox, BoxTitle, Database, Grid, LinkCard, List, SignalStream, SquareLogo, } from '@site/src/components/GettingStarted'; import { IconTitle } from '@site/src/components/shortcodes/index'; Prisma Accelerate [Prisma Accelerate](https://www.prisma.io/accelerate) is a fully managed global connection pool and caching layer for your existing database, enabling query-level cache policies directly from the Prisma ORM. With 15+ global regions, the connection pool scales your app for a global audience, particularly for serverless deployments that risk connection timeouts during peak times. Accelerate’s global cache, hosted in 300+ locations, ensures a fast experience for users, regardless of your database’s location. You can configure query-level caching strategies directly in your code with Prisma ORM, making setup and tuning easy. Together, the connection pool and cache allow you to scale effortlessly and handle traffic spikes without infrastructure concerns.
## Supported databases Accelerate works with the database you already have, whether it is publicly accessible, or via an IP allowlist.
## In this section --- # General URL: https://www.prisma.io/docs/platform/about ## Overview The [Console](https://console.prisma.io/login) enables you to manage and configure your projects that use Prisma Data Platform (PDP) products, and helps you integrate them into your application: - [Accelerate](/accelerate): Speeds up your queries with a global database cache with scalable connection pooling. - [Optimize](/optimize): Provides you recommendations that can help you make your database queries faster. - [Prisma Postgres](/postgres): A managed PostgreSQL database that is optimized for Prisma ORM. ## Concepts The Console workflows are based on four main concepts: - [**User account**](#user-account): In order to use PDP products, you need to have a PDP user account. A _user_ will typically create one user account to manage all their workspaces, projects and environments. The _user_ can also be invited to join other workspaces to collaborate on the projects in that workspace. - [**Workspaces**](#workspace): A user account can belong to multiple workspaces. A workspace typically represents a _team_ of individuals working together on one or more projects. **Billing is on a workspace level**, i.e. the invoice for a workspace at the end of the month captures all costs associated with the projects in a given workspace. - [**Projects**](#project): A project belongs to a workspace. It typically represents the _application_ or _service_ a team is working on. - [**Environments**](#environment): An environment belongs to a project. It typically maps to a _development stage_, like `Development`, `Staging` or `Production`. **API keys are provisioned on the environment level**, and products are configured per environment as well (e.g. the database connection string used for Accelerate). Here is a visual illustration of how these concepts relate to each other: ![How the concepts of the Platform (user account, workspaces, projects, and environments) relate to each other ](/img/platform/pdp-concepts.png) ### User account A user account is the prerequisite for any interactions with PDP products. You can use it to manage your workspaces (and their projects). A user account can be invited to collaborate on workspaces created by other users as well. If you need to delete your user account, go [here](/platform/support#deleting-your-pdp-account). ### Workspace You can create several workspaces. A workspace is an isolated space to host projects. A workspace can have multiple user accounts associated with it so that multiple users can collaborate on the the projects in the workspace. In each workspace, you can: - view and manage all projects (and their environments) in that workspace. - manage billing, i.e. select a [subscription plan](https://www.prisma.io/pricing?utm_source=docs&utm_medium=platform-docs), configure payment methods, or view the invoice history. - view the usage of your enabled PDP products across all projects in that workspace. - invite other users to collaborate in the workspace. - access the [Optimize dashboard](https://console.prisma.io/optimize?utm_source=docs&utm_medium=optimize-docs) to measure query performance and receive AI-powered recommendations. #### Optimize You can access Optimize within your [Prisma Data Platform account](https://console.prisma.io/optimize) workspace. ##### Accessing the Optimize dashboard To access the Optimize dashboard in your desired workspace: 1. Click the **Optimize** tab on the left navigation. 2. Click the **Launch Optimize** button. ##### Generating an Optimize API key To obtain the Optimize API key: 1. Navigate to the workspace where you want to use Optimize. 2. Ensure that Optimize is launched. If it isn't, click the **Launch Optimize** button. 3. In Optimize, click your profile name in the top right corner of the navbar. 4. Select **Settings**. 5. Click **Create API key**. 6. Enter a name for the API key in the **Name** field, then click **Create**. 7. Copy the API key and store it securely. This will be used in your project's [`.env` file](/optimize/getting-started#22-add-the-optimize-api-key-to-your-env-file) via the `"OPTIMIZE_API_KEY"`. Finally, click the **"I've stored it securely"** button. You now have your Optimize API key. ### Project In each workspace, you can create several projects. A project typically represents an application (a product or service). You typically have one [Prisma schema](/orm/prisma-schema/) per project. In each project, you can: - view and manage all environments in that project. The number of project you can create in a workspace depends on the [subscription plan](https://www.prisma.io/pricing?utm_source=docs&utm_medium=platform-docs) configured in that workspace. ### Environment An environment is an isolated space used to provision PDP products for a specific project. Environments typically correspond to development stages, such as `Development`, `Staging`, or `Production`. Every new project begins with a _default_ environment named `Production`. The default environment ensures that the project always has at least one active environment. It cannot be deleted unless another environment is designated as the default. In each environment, you can: - enable, disable and configure PDP products (Optimize, Accelerate, ...). - generate API keys. - for **Accelerate**: - set your database connection string. - configure the _region_ where Accelerate's connection pool is running. - change the connection pool size. - configure query duration and query response size limits. - enable static IP. The number of environments you can create in a project depends on the [subscription plan](https://www.prisma.io/pricing?utm_source=docs&utm_medium=platform-docs) configured in your workspace. ## Database connection management The **Database** tab in the left panel of a project environment lets you configure and manage connections to your remote database. Within this tab, the **Connections** section displays a table with the following columns: | Column Name | Description | |-------------|-------------| | **Hint** | Provides the URL structure for the database in use. | | **Static IP** | Indicates whether static IP is enabled for the database and associated products. | | **Products** | Lists the products that are enabled using the database URL. | | **Action** | Allows you to disable all active products and remove the connection. | ## Billing The [subscription plan](https://www.prisma.io/pricing?utm_source=docs&utm_medium=platform-docs) you select in your workspace determines how many projects and environments you can create in that workspace: | | **Starter** | **Pro** | **Business** | **Enterprise** | | ---------------- | :---------- | ----------- | ------------ | -------------- | | **Projects** | 5 | 60 | 180 | Custom | | **Environments** | 2 / project | 6 / project | 12 / project | Custom | | **Databases** | 10 | 60 | 180 | Custom | ### Per-workspace billing Billing is set up on a per-workspace basis: - A subscription plan is selected per workspace. That means, a user account can belong to multiple workspaces where each workspace uses a different plan. - A payment method is selected per workspace. That means, a user account can belong to multiple workspaces where each workspace has a different payment method. At the end of a billing period, your selected payment method will be charged with the incurred costs of products across _all_ projects (and their environments) in that workspace. You can configure all billing details in the **Billing** section of your workspace. ### Prorated billing All base plan prices are prorated, which means you're only billed for the duration of your subscription to a specific plan. In addition, you're also billed for any usage costs you've incurred during your subscription. For example: - if you subscribe to our **Pro** plan on the 15th day of a month, you'll only be charged the base plan price for the days left in that month. - if you downgrade your subscription plan (e.g. from **Business** to **Pro**) after 10 days of a 30-day month, you'll be charged for 10 days of the base price of the **Business** plan and 20 days for the base price of the **Pro** plan. Visit our [pricing page](https://www.prisma.io/pricing?utm_source=docs&utm_medium=platform-docs) for more details. ### Downgrading a subscription plan If you downgrade a subscription plan, you may need to delete some of your projects and/or their environments in order to adhere to the [limits](#environment) of the newly selected plan. For example, if your workspace is on a **Business** plan and currently has 14 (out of 15) projects, you will need to delete at least 4 projects to adhere to the project limit of the **Pro** plan. Additionally, you need to make sure that the remaining projects don't have more than 6 environments per project to adhere to the environment limit of the **Pro** plan. You also need to disable features that are exclusive to **Pro** or **Business** plans, such as Static IPs. Once these adjustments are made, including disabling Static IPs, you can proceed to downgrade your subscription plan. ## Programmatic access via the Platform CLI In addition to the web interface of the Console, the Prisma CLI provides another way to interact with your PDP account and manage PDP products. This can be useful if you need programmatic access, e.g. for integrating it into CI workflows. Read more about the [Prisma CLI](/platform/platform-cli). ## API keys An API key is required to authenticate requests from your Prisma Client to products such as Prisma Accelerate and Prisma Optimize. You may generate multiple API keys per environment and manage those via the **API Keys** section in an environment. --- # Maturity levels URL: https://www.prisma.io/docs/platform/maturity-levels Prisma releases updates to Prisma Data Platform multiple times per week, as opposed to the Prisma ORM that we release on a set schedule every few weeks. This is why we consider the lifecycle and process for maturing features in Prisma Data Platform differently. You can [check out the releases and maturity process for the Prisma ORM](/orm/more/releases) for further details. You can find information about releases across _all_ Prisma tools and products in the [changelog](https://www.prisma.io/changelog). ### Early Access If a feature on the Prisma Data Platform is labeled as **Early Access**: - We have validated a problem and are considering a solution to it but are not certain whether that solution is complete or a perfect fit. - We want to gather more feedback and adjust the solution as necessary, knowing that users are prepared for significant breaking changes - We reserve ourselves the right to throttle or remove access to a feature in Early Access to preserve the stability of the platform, or enforcing its use to stay within the scope defined in our [Terms of Service](https://pris.ly/terms). As always, your feedback in our [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=inline_text) is invaluable to shape the design of the features. This will help us ensure that they can solve your problems in the best way possible. ### Preview If a feature on the Prisma Data Platform is labeled as **Preview**: - We have refined the software based on the valuable feedback we obtained during the Early Access phase. - We developed the feature further, bringing it closer to the final version, though it's not completely ready for production usage. - We have lifted the invite gate, so users no longer need an invitation to access the feature. Users just need to sign up to gain access. - We have increased the stability of the software compared to the Early Access phase. While there might still be some issues, they should be less frequent and less critical. - We use the Preview phase as a final stress test to ensure the product is ready for heavy production workloads. We recommend testing the product in a staging environment and welcome any feedback in our [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=inline_text). This will assist us in improving the product for its final release. ### General Availability If a feature in the Prisma Data Platform is Generally Available: - The solution has undergone extensive testing and, based on significant feedback, is deemed stable and ready for production use cases. --- # Support URL: https://www.prisma.io/docs/platform/support Your feedback is invaluable, and we encourage you to share your experiences with us on [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=intro_text). ## Support Your support options are based on your workspace's active plan. For more details, take a look at our [pricing page](https://www.prisma.io/pricing). ### Community support Reach out to us in our [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=inline_text). ### Standard support - Email support, [support@prisma.io](mailto:support@prisma.io), or reach out via the Console - 2 business days, Mon-Fri, 9am-5pm CET ### Premium support - Email support, [support@prisma.io](mailto:support@prisma.io), or reach out via the Console - 1 business hour, Mon-Fri, 9am-5pm CET ### Dedicated support Dedicated contact person. ## Deleting your PDP account If you want to delete your PDP account, **email us at [support@prisma.io](mailto:support@prisma.io)** specifying the email id or GitHub handle with which you signed up. To ensure that you're not accidentally disabling any infrastructure powering one of your applications, we require that you **disable Accelerate in _all_ environments of _all_ your projects** that live in the account to be deleted. Additionally there should be no active subscriptions in the account to be deleted. Please cancel any active subscriptions before requesting account deletion. --- # About the Platform CLI URL: https://www.prisma.io/docs/platform/platform-cli/about This guide demonstrates how to access the Prisma Data Platform using the [Prisma CLI](/orm/tools/prisma-cli). Get started by ensuring you have the Prisma CLI installed, following our setup [instructions](/orm/tools/prisma-cli#installation). This integration, now in Early Access, expands the capabilities of the Prisma CLI, enabling management of your Platform projects directly from the command line. For a detailed overview of all the commands, please refer to the [Commands page](/platform/platform-cli/commands). --- # Commands URL: https://www.prisma.io/docs/platform/platform-cli/commands This document describes the Prisma Data Platform's integrated Prisma CLI commands, arguments, and options. ## Getting started To get started, ensure you have the [Prisma CLI](/orm/tools/prisma-cli) updated to version `5.10.0` or later. This is necessary to access the Platform through the Prisma CLI. :::info 💡 When using commands, always start with `prisma platform` and include the `--early-access` flag to enable the use of the Prisma Data Platform whilst still in early access. ::: ## Authentication ### `platform` #### `auth login` Opens a browser window that allows you to log into your Prisma Data Platform account or create a new one. Currently, GitHub is the only supported login method. We do have plan to add support for signing in with Google and email/password. ```bash npx prisma platform auth login --early-access ``` #### `auth logout` Logs out of your Prisma Data Platform account. ```bash npx prisma platform auth logout --early-access ``` #### `auth show` Displays information about the currently authenticated user. ```bash npx prisma platform auth show --early-access ``` ### Workspace Management ### `platform` #### `workspace show` Lists all workspaces available to your account. ```bash npx prisma platform workspace show --early-access ``` ### Project Management ### `platform` #### `project show` Lists all projects within the specified workspace. ```bash npx prisma platform project show \ --workspace $INSERT_WORKSPACE_ID \ --early-access ``` ##### Arguments | Argument | Type | Required | Description | | ------------------ | -------- | -------- | --------------------------------------------------------------------------------------------------------------------------- | | `--workspace` `-w` | `string` | yes | The workspace id.

**Hint:** You can view your workspace ids with the [`workspace show`](#workspace-show) command. | #### `project create` Creates a new project within the specified workspace. ```bash npx prisma platform project create \ --workspace $INSERT_WORKSPACE_ID \ --name "INSERT_PROJECT_NAME" \ --early-access ``` ##### Arguments | Argument | Type | Required | Description | | ------------------ | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------- | | `--workspace` `-w` | `string` | yes | The workspace `id`.

**Hint:** You can view your workspace ids with the [`workspace show`](#workspace-show) command. | | `--name` `-n` | `string` | no | The display name for the project.

If omitted, a default project name will be generated for you. | #### `project delete` Deletes the specified project. ```bash npx prisma platform project delete \ --project $INSERT_PROJECT_ID \ --early-access ``` ##### Arguments | Argument | Type | Required | Description | | ---------------- | -------- | -------- | --------------------------------------------------------------------------------------------------------------------- | | `--project` `-p` | `string` | yes | The project `id`.

**Hint:** You can view your project ids with the [`project show`](#project-show) command. | ### Environment Management ### `platform` #### `environment show` Lists all environments within the specified project. ```bash npx prisma platform environment show \ --project $INSERT_PROJECT_ID \ --early-access ``` ##### Arguments | Argument | Type | Required | Description | | ---------------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------- | | `--project` `-p` | `string` | yes | The project `id`.

**Hint:** You can view your project ids with the [`project show`](#project-show) command. | #### `environment create` Creates a new environment within the specified project. ```bash npx prisma platform environment create \ --project $INSERT_PROJECT_ID \ --name $INSERT_ENVIRONMENT_NAME \ --early-access ``` ##### Arguments | Argument | Type | Required | Description | | ---------------- | -------- | -------- | --------------------------------------------------------------------------------------------------------------------- | | `--project` `-p` | `string` | yes | The project `id`.

**Hint:** You can view your project ids with the [`project show`](#project-show) command. | | `--name` `-n` | `string` | no | The display name for the environment.

If omitted, a default environment name will be generated for you. | #### `environment delete` Deletes the specified environment. ```bash npx prisma platform environment delete \ --environment $INSERT_ENVIRONMENT_ID \ --early-access ``` ##### Arguments | Argument | Type | Required | Description | | -------------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `--environment` `-e` | `string` | yes | The environment `id`.

**Hint:** You can view your environment ids with the [`environment show`](#environment-show) command. | ### API Key Management ### `platform` #### `apikey show` Lists all API keys for the specified environment. ```bash npx prisma platform apikey show \ --environment $INSERT_ENVIRONMENT_ID \ --early-access ``` ##### Arguments | Argument | Type | Required | Description | | -------------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `--environment` `-e` | `string` | yes | The environment `id`.

**Hint:** You can view your environment ids with the [`environment show`](#environment-show) command. | #### `apikey create` Creates a new API key for the specified project. ```bash npx prisma platform apikey create \ --environment $INSERT_ENVIRONMENT_ID \ --name $INSERT_API_KEY_NAME \ --early-access ``` ##### Arguments | Argument | Type | Required | Description | | -------------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `--environment` `-e` | `string` | yes | The environment `id`.

**Hint:** You can view your environment ids with the [`environment show`](#environment-show) command. | | `--name` `-n` | `string` | no | The display name for the API key.

If omitted, a default API key name will be generated for you. | #### `apikey delete` Deletes the specified API Key. ```bash npx prisma platform apikey delete \ --apikey $INSERT_API_KEY_ID \ --early-access ``` ##### Arguments | Argument | Type | Required | Description | | ---------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------ | | `--apikey` | `string` | yes | The API key `id`.

**Hint**: You can view your API key ids with the [`apikey show`](#apikey-show) command. | ### Prisma Accelerate ### `platform` #### `accelerate enable` Enables Prisma Accelerate for the specified environment. ```bash npx prisma platform accelerate enable \ --environment $INSERT_ENVIRONMENT_ID \ --url "postgresql://username:password@host:port/database" \ --region $INSERT_CONNECTION_POOL_REGION \ --apikey true \ --early-access ``` ##### Arguments | Argument | Type | Required | Description | | -------------------- | --------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `--environment` `-e` | `string` | yes | The environment `id`.

**Hint:** You can view your environment ids with the [`environment show`](#environment-show) command. | | `--url` | `string` | yes | Your database connection string. | | `--region` | `string` | no | The region for Prisma Accelerate’s managed connection pool.

View the list of available regions [here](/accelerate/faq#what-regions-is-accelerates-connection-pool-available-in).

**Hint**: Select the region _nearest_ your database for optimal latency. | | `--apikey` | `boolean` | no | If yes, a new API key will be generated for the associated environment. | #### `accelerate disable` Disables Prisma Accelerate for the specified environment. ```bash npx prisma platform accelerate disable \ --environment $INSERT_ENVIRONMENT_ID \ --early-access ``` ##### Arguments | Argument | Type | Required | Description | | -------------------- | -------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `--environment` `-e` | `string` | yes | The environment `id`.

**Hint:** You can view your environment ids with the [`environment show`](#environment-show) command. | ## Help Have a question? Let us know, we’re here to help. Reach out to us on [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=generated_text_cta). --- # Platform CLI URL: https://www.prisma.io/docs/platform/platform-cli/index ## In this section --- # Platform URL: https://www.prisma.io/docs/platform/index Learn about the main concepts and workflows of the [Prisma Data Platform](https://console.prisma.io/login). ## In this section --- # Writing style URL: https://www.prisma.io/docs/about/style-guide/writing-style ## Audience We assume that our audience has basic software development knowledge. Our audience know how to use their tools, such as their IDE and a terminal window. Many of our users are familiar with advanced software development concepts and techniques, but we cannot assume this in the docs. We cannot assume that our users have any database knowledge. ## Simplify It's a good principle of technical communication to write as simply as possible. This is harder than it sounds, but the extra work is worth it to make clearer, more readable docs. It's particularly important when you write for a global audience, not all of whom are fluent with English. - Use short paragraphs - Stick to short, simple sentences. Where possible, avoid sentences with multiple clauses. - English has many synonyms - where possible, choose the simplest available word for the job. Examples: "in" instead of "within", "use" instead of "utilize". - Use bullet lists to break up complex sentences into component points - Use examples - Use [appropriate text emphasis, such as bold and italics](/about/style-guide/spelling-punctuation-formatting#text-emphasis) to make your writing clearer - Use tables to set out complex information - Use diagrams to make complex workflows or concepts easier to visualize ## Tone of voice Write in a calm, assured tone of voice. Our tone is friendly and direct, but [we don't use slang](#avoid-emojis-slang-and-metaphors). ## Write in US English US English is the most globally recognized form of English. Use US English punctuation, grammar, and spelling. For example: - `color` over `colour` - `behavior` over `behaviour` - `Prisma plans to` over `Prisma plan to` ## Avoid emojis, slang, and metaphors Avoid emojis, idiomatic expressions, slang, and metaphors. Prisma has a global community, and the cultural meaning of these items might be different around the world, and can change over time. ## Avoid imprecise pronouns like "it" or "that" Try to be as specific as possible when you refer to a specific noun. Do not refer to the noun as "it" unless you have just defined the proper noun in a previous sentence or clause. Even then, your writing might be clearer for international audiences if you specify the noun again. In particular, avoid starting sentences with "It". ## Write in the second person The second person ("you") gives a conversational tone and speaks directly to the reader. Avoid the first person ("I", "we", "let's", and "us"). Example: > "You must commit the entire `prisma/migrations` folder to source control." Exception: Use "we" when you refer to Prisma the organization. For example, here Prisma (the organization) recommends a course of action: > "We recommend that you share a single instance of `PrismaClient` across your application". ## Use inclusive language When you refer to one or more people in the third person, use inclusive, gender-neutral language. Use "they/them/their" instead of "he/him/his" or "she/her/her". Avoid gender-specific words like "guys". ## Jargon > Jargon: (n.) special words or expressions that are used by a particular profession or group and are difficult for others to understand. The Prisma docs include a lot of technical detail, and jargon is unavoidable. However, we strive to use as little jargon as possible. When you use jargon, follow these guidelines: - If you can explain the jargon in a few words, then you might prefer to explain it there and then. Use your judgement to decide whether that is best for this doc. - For longer explanations, link to a definition elsewhere. - If the jargon is specific to Prisma, then link to a definition in our docs. - If the jargon is _not_ specific to Prisma, check if you can find the definition quickly with a web search. If so, then do not explain the term or link to a definition. We can reasonably expect users to know the jargon or to find an explanation for themselves. - Only link on the first instance of a jargon term in a logical section of the docs. A logical section is a section of the docs that we might expect someone to read at one time. Typically, it is a page, or a self-contained part of a page that comprises one or more headed sections. - When you link to an external definition, choose a credible source. Wikipedia is acceptable, and official third-party documentation is better. ## Use active voice Use active voice instead of passive voice. It's a more concise and straightforward way to communicate. For example: - (passive) The `for` loop in JavaScript is used by programmers to… - (active) Programmers use the `for` loop in JavaScript to… When our software or third-party software does something, state which module or component carries out the action, if this is important to the user. - "Prisma Client returns all `DateTime` as ISO 8601-formatted strings." Where the module or component is not important to the user, say that Prisma (or the name of the third-party software) carries out the action: - "Prisma reads from the system's environment when it looks for environment variables..." - "This is because MongoDB returns a cursor that is attached to your MongoDB session..." Sometimes you can omit the acting component or module altogether: - “Refer to the generated log file in `/directoryX`.” ## Be assertive Use assertive language. Good: - Use the `createMany` method to create multiple records in a single transaction - You can use nested writes to create a user and that user's posts at the same time Avoid: - This example tries to... - You might be able to... - You could use... Assertive language in procedures: Good: - Install dotenv-cli Avoid: - Please install dotenv-cli ## Use "that" to clarify sentences Example: "Ensure that you rebuild your schema.". See: ["That" as a conjunction for noun clauses](https://academicguides.waldenu.edu/formandstyle/writing/grammarmechanics/that). ## Use the present simple tense - Write in the [present simple](https://en.wikipedia.org/wiki/Simple_present) tense. - Use present simple even when you want to write about something that will happen as the result of a user action: say that the result happens, not that it will happen. ```md When you run this command, Prisma writes the following log file. When you run this command, Prisma will write the following log file. ``` ## Indicate when something is optional When a paragraph or sentence offers an optional path, the beginning of the first sentence should indicate that it’s optional. For example, "if you’d like to learn more about xyz, see our reference guide" is clearer than "Go to the reference guide if you’d like to learn more about xyz." This method allows people who would not like to learn more about xyz to stop reading the sentence as early as possible. It also allows people who would like to learn more about xyz to recognize the opportunity to learn quicker instead of accidentally skipping over the paragraph. For optional steps in a procedure, a succinct way to convey this is to precede the step with "Optional:". For example: 5. Optional: In the **Tags** field, specify one or more tags for your file. Separate multiple tags with commas. ## Code examples Start all query examples with a constant. This gives you a noun to refer to later in the document, and in most cases this clarifies the example. Example: ```ts const aggregations = await prisma.user.aggregate({ ... }) ``` --- # Word choice URL: https://www.prisma.io/docs/about/style-guide/word-choice ## Avoid words like "easy" and "just" Avoid words like "easy", "just", "simple", and "basic". If users have a hard time completing the task that is supposedly "easy," then they will question their abilities, or get aggravated by the docs. Consider using more specific descriptors. For example, when you say the phrase "deployment is easy," what do you really mean? Is it easy because it takes fewer steps than another option? If so, use the most specific descriptor possible, which in that case would be "this deployment method involves fewer steps than other options." For even more inclusive docs, avoid phrases that assume a reader’s experience or skill level, like "just deploy it and you’re done" or "for a refresher (when you refer to a completely different doc that someone might not have read)". Often, when you rephrase, you get stronger sentences that work in a wider range of contexts. ## Avoid Latin terms These are common in English, but can be problematic for non-first-language speakers. Some of them can be confusing even to native English speakers. For example: | Avoid | Good | | ----- | ----------------------------------------------------------------------------------------------------------- | | et al | "and others" | | etc. | "and so on", or list all of the cases | | i.e. | "in other words" | | e.g. | "such as" or "for example" | | via | "with" or other equivalent, as in "Now you can start to send queries with the generated Prisma Client API") | ## Avoid gerunds ("ing" verb forms) Avoid gerunds (the "ing" form of verbs). For example, use "Get started" instead of "Getting started". This guideline applies to headings and body text. Examples: | Avoid | Good | | ----------------------------------------------- | ----------------------------------------- | | Test the certificate using a browser | Test the certificate with a browser | | Excluding fields | Exclude fields | | If you are using Node.js version 18 or later... | If you use Node.js version 18 or later... | | You can do this by rebuilding Prisma Client | To do this, rebuild Prisma Client | | When designing your schema... | When you design your schema... | Note that nouns ending in "ing" are fine - for example "Tracing". ## Avoid incomplete sentences before lists When you introduce a list, do not use an incomplete sentence. ### Use You can configure your schema in the following ways: - Item 1 - Item 2 ### Avoid You can: - Item 1 - Item 2 ## When you refer to other parts of the docs Use the following terms: - Page - Section ## Records Refer to rows in the database as **records**. For example: "The following `create` query creates a single `User` **record**." Do not use: - Entry - Row - Object ## Model property Model property refers to the top-level `PrismaClient` properties that refer to models: ``` const result = await prisma.user.findMany(...) // "user" model property const result = await prisma.post.findMany(...) // "post" model property ``` ## Version numbers - Refer to version numbers as "version x.x.x" - When you compare version numbers, use "before" and "after" (or "later") - Do not use "lower" and "higher" ```md This feature is in Preview in versions 3.5.0 and later. This feature is in Preview in v3.5.0 and higher. ``` When you write about a specific version, make it clear _what product_ you are referring to. For example, in the following sentence, version 3.11.1 might refer to Prisma or to MongoDB: _This filter is available for MongoDB only in versions 3.11.1 and later._ When the product is not clear from the context, explicitly mention the product name in front of the version number. _This filter is available for MongoDB only in Prisma versions 3.11.1 and later._ ### In deprecation notices, mention the deprecation version number but not the planned removal version number When you explain that a feature is deprecated, include the version number in which it was deprecated. However, plans change. To keep docs lean and accurate, do not mention the version in which Prisma plans to remove the feature. ```md From v3.0.0, the `command name` command is deprecated. From v3.0.0, the `command name` command is deprecated. We plan to remove `command name` in v.4.0.0. ``` ## Abbreviate terms If you want to abbreviate a term, write it out fully first, then put the abbreviation in parentheses. After that, you can use the abbreviation for the rest of the page. For example, "In computer science, an abstract syntax tree (AST) is …". See also: [Jargon](/about/style-guide/writing-style#jargon) ## Avoid ambiguous English words Avoid the following common words in English, because they are ambiguous to many readers. | Word to avoid | Reason to avoid | Use the following word instead | | -------------------------------- | -------------------------------------------------- | ------------------------------------------------------------------------------------ | | As | Can mean "because" or "at the same time as" | "Because", or "At the same time", as appropriate | | Since (to mean "because") | Can also mean "after" (as in "since you upgraded") | "Because" | | May (to mean "might") | Can also mean "is permitted to" | "Might" | | Should (to mean "ought to") | Can also mean "might happen" | "Must": "You must rebuild Prisma Client", or

Omit: "Rebuild Prisma Client." | | Once (to mean "when" or "after") | Can also mean "happens once" | "When": "When the build completes..." | | Wish (to mean "want") | Not always clear internationally | "Want" | ## Use clear hyperlinks Avoid the constructions "click here" or "here" for link text. They are considered bad practice on the web. ```md Read more in the [Prisma ORM docs](/orm) Read more in the Prisma ORM docs [here](/orm) ``` If your link text is the title of the destination page, use sentence case: ```md For more information, see [Relation queries](/orm/prisma-client/queries/relation-queries). For more information, see [Relation Queries](/orm/prisma-client/queries/relation-queries). ``` When it is obvious what the link destination is (for example if you've explained the concept in the preceding sentence), then a very concise (and maintainable) way to provide a link to further information is as follows: ```md [Learn more](/orm/prisma-client/queries/relation-queries) ``` ## Specific terms ### "Preview" and "general availability" Use lower case for these. For "GA", the abbreviation of general availability, use all caps. ```md We made composite types generally available in version 3.12.0. They were previously available in preview from version 3.10.0. We made composite types Generally Available in version 3.12.0. They were previously available in Preview from version 3.10.0. ``` ### SQL Write "a SQL query", not "an SQL query". Example: "A SQL database...". ### macOS Good: macOS Bad: Mac OS, MacOS, or any other variant ### Terminal window Use the term "terminal window". Do not use "command prompt" or "shell". Example: ``` Open a terminal window. ``` ### Set up/setup This can be a noun ("setup") or verb ("set up") and as such can cause confusion. Try to avoid, and use an alternative term. For example, "configure" or "enable". If you must use it, ensure that you use the correct form. Remember to check in code snippets, where it might lurk in the code comments. ### Relations When referring to relations, use the following forms: | Avoid | Good | | ----- | ------------ | | 1-1 | One-to-one | | 1-n | One-to-many | | m-n | Many-to-many | ### The `prisma` root command We often refer to `prisma` CLI commands such as `prisma db push`. - The long form of these commands includes the `prisma` root command. For example: `prisma db push`. - The short form of these commands omits the `prisma` root command. For example: `db push`. `prisma` CLI commands only work when the user includes `prisma`. In most cases, use the long form to help docs users who drop into the docs at that point. The long form also let docs users copy and paste a working command into their terminal windows. Use the long form in these circumstances: - When you include a `prisma` command in a code box. - When you include a `prisma` command in a procedure. It is OK to use the short form in the following circumstances. This can help with brevity and readability in the docs. - When you discuss a `prisma` command, for example in reference material. Example: ["`db push` uses the same engine as Prisma Migrate..."](/orm/prisma-migrate/workflows/prototyping-your-schema) - When you mention a `prisma` command in a heading. [Example](/orm/reference/prisma-cli-reference#init) ### Possessive s Indicate owner and ownership clearly and do not use possessive _s_. When you avoid possessive s, you also avoid: - stringing together too many nouns - issues related to localization and how well international readers understand what you document ```md Change the database connection string of an environment Change the environment's database connection string ``` ### enter vs [*provide, type*] Use _enter_ for the action of filling out or typing in a text box or input field. Do not use _provide_ or _type_. ```md In **Display Name**, enter a name for your project. In **Display Name**, type a name for your project. In **Display Name**, provide a name for your project. ``` ### _clear_ vs [*deselect*, *unselect*, *uncheck*, *unmark*] Use _clear_ to guide readers to remove the check mark from a checkbox. ```md Clear **Include sample data**. Deselect the **Include sample data** checkbox. ``` ### _select_ vs _choose_ _Choose_ conveys the idea of making a choice in general, while _select_ works better in the context of fine-picking an option or making a UI selection among a list of options. Use _select_ when you guide readers which UI option to select. ```md From **Payment method**, select **Wire transfer**. ``` Use _choose_ when you make a conceptual description of choosing one option over another. ```md You can choose to host your project in Vercel or Netlify. ``` ### checkbox vs ~~check box~~ Use _checkbox_. See [Avoid excessive use of UI terminology](/about/style-guide/user-interace-guidelines#avoid-excessive-use-of-ui-terminology). --- # Spelling, punctuation, and formatting URL: https://www.prisma.io/docs/about/style-guide/spelling-punctuation-formatting ## Avoid contractions In keeping with our conversational style, some contractions are OK: - Contractions that include the words "is" or "are". For example: it's and you're. - However, use contractions sparingly. However, avoid other contractions. For example: - It'll (use "It will") ## Text emphasis Use text emphasis (**bold**, and _italic_) sparingly. In keeping with the calm tone of our docs, and to help readability, avoid a sea of emphasized and formatted text. Italic and bold text can be a great way to emphasize certain parts of your sentence to the reader. Use bold text more sparingly, and only when you want some text to stand out from the entire paragraph (so that it's visible when a reader only "scans" the page instead of properly reading it). Use italics for words that introduce new concepts for the first time. Do not use ALL CAPS to emphasize text. If you are in doubt about whether to emphasize some text, then don't do it. ### UI elements For the names of GUI elements (buttons, drop-down menus, and so on), use **bold**. Also use the same capitalization as in the GUI. For example: 1. In the `**File**` menu, select `**Open...**`. ### Avoid exclamation points In keeping with our calm tone, do not use exclamation points (exclamation marks). Exception: they are acceptable in congratulatory or welcome messages, for example: "Congratulations - you've completed the tutorial!" ### Capitalize and spell out proper nouns Although you might be tempted to use abbreviations like "Postgres" (instead of the official proper noun "PostgreSQL") or not worry about casing when writing "Javascript" (instead of "JavaScript"), we use the official forms of proper nouns. A few common examples are: - Node.js (instead of Node or Node.JS) - JavaScript and TypeScript (instead of JavaScript and Typescript or JS and TS) - PostgreSQL (instead of Postgres or Postgresql) - MongoDB (instead of Mongo) - GitHub (instead of Github) - For JSON, see [Special case: JSON](#special-case-json) If you're not sure about the spelling of a proper noun, check its official web site. ### Titles and headings - Use sentence case for titles and headings: only the initial word is uppercase (exception: [capitalize proper nouns](#capitalize-and-spell-out-proper-nouns)) - [Avoid gerunds](/about/style-guide/word-choice#avoid-gerunds-ing-verb-forms) ("Configure the database", not "Configuring the database") - Do not use punctuation at the end of a title or heading unless a question mark is required - Use ``code`` for code in headings - this is required by our navigation elements ## Tables, bullet lists, and numbered lists Tables and lists are often the most concise way to present information. Use these elements whenever they feel appropriate. Here are a few guidelines: - Use a bullet list when the order of the list doesn't matter (e.g. an enumeration of the features of a database which don't have an inherent order). - Use a numbered list only when the order of the list matters (e.g. when providing step-by-step instructions where one step builds on the previous). - Use a table to describe things that share a number of similar properties/characteristics (e.g. the parameters for an API call which all have a "name", a "type", are required or optional and need a description). - For both numbered/ordered lists and bullet lists, add a period on the end if it is a complete sentence. This is most common in ordered lists, with a series of steps. ## Hyphens Use hyphens according to these [rules](https://www.grammarbook.com/punctuation/hyphens.asp). Sometimes there are some terms where it's not clear whether to use a hyphen or not. To strive for consistency, we list those terms here. ### Spell without a hyphen - Use case - Command line (when referring to it as a noun: "On the command line". Use a hyphen when it's an adjective: "This command-line option...") - Auto format - Type safety (see below for guidelines on "type safe") - File name - Compile time (when you use it as a noun: "... at compile time". Use a hyphen when it's an adjective: "This compile-time operation...") ### Spell as one word - Autocomplete - Codebase ### Type-safe, type safe, and type safety - "The code is type safe." (adjective after the noun) - "This is type-safe code." (adjective before the noun) - "A key feature of Prisma ORM is type safety." (noun) ### Data source and `datasource` - The `datasource` block - "You must regenerate Prisma Client when you introduce a new data source" ## Files and file types When you refer to a file or file type, use lower case and code format, and include the dot. Use "an" as the preposition if the filename extension, when pronounced, starts with a vowel, otherwise use "a": - a `.jpg` file - an `.xls` file - an `.env` file - For json files, see [Special case: JSON](#special-case-json) Note: when you refer to a specific file, use the capitalization that is used in the file name: - the `schema.prisma` file ### Special case: JSON - When you refer to JSON in general, use all caps and no code format - When you refer to the Prisma `Json` API, use `Json` - When you refer to a JSON file, use the formatting rules above: "a `.json` file" ### Use inline code format for paths and file names For example: - "The generated Prisma Client is located in the `./node_modules/.prisma` folder by default." - "The `schema.prisma` file is located in..." - "To use multiple `.env` files..." ## Use inline code format when referring to strings in text For example: "The following query returns all records where the `email` field is equal to `Sarah`." ## Avoid excessive code formatting Documents can quickly get visually cluttered if they have too much special formatting. Our docs are highly technical, and we often refer to code snippets or technical keywords that appear in the user's code. For these keywords, it's appropriate for us to use code formatting. However, we should not refer to general technologies (such as JSON) with code formatting: For example: Prisma automatically converts JavaScript objects (for example, `{ extendedPetsData: "none"}`) to JSON. ## Make lists clear with the Oxford Comma Use the Oxford Comma except in titles. It is a comma used after the penultimate item in a list of three or more items, before "and" or "or". It makes things clearer. Example: "... an Italian painter, sculptor, and architect". In rare cases, the Oxford Comma can make a list less clear. In this situation, re-order the list where possible to make the meaning clear. ## Code snippets ### Introduce all code snippets Write a short introductory sentence that: - Explains what the code snippet does - Links to reference documentation if applicable For example: This [`createMany()`](/orm/reference/prisma-client-reference/#createmany) query does the following: - Creates several `User` records - Creates several nested `Post` records - Creates several nested `Category` records ### Show the result of a query wherever possible Use the [``](/about/docs-components/mdx-examples#code-with-result) component to show a query and the results of that query. ### Use `highlight` comments to highlight code If you need to highlight lines in your code samples, use the [`highlight` magic comments](/about/docs-components/mdx-examples#code-block-with-highlighted-code). For example: ```` ```prisma generator client { provider = "prisma-client-js" //highlight-next-line previewFeatures = ["namedConstraints"] } ``` ```` ### Format code blocks and inline code Use the following as reference when creating and editing docs: [formatting inline code and code blocks](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code). ### Emphasize placeholders Placeholders are a tricky topic in technical documentation and are one of the most common sources of confusion, especially for beginners. To strive for consistency, placeholders in the Prisma docs: - are spelled in all-uppercase letters - are prefixed and suffixed with two underscores - use descriptive terms As an example, consider the following code block where `__DATABASE_CONNECTION_URL__` is a placeholder for the PostgreSQL connection URL: ```prisma datasource db { provider = "postgresql" url = "__DATABASE_CONNECTION_STRING__" } ``` Whenever you use a placeholder, explain how to obtain a value for the placeholder, or link to another resource that explains this. Explicitly call out that this is a placeholder that must be replaced with a "real value". Include an example of what that real value might look like: ```prisma datasource db { provider = "postgresql" url = "postgresql://opnmyfngbknppm:XXX@ec2-46-137-91-216.eu-west-1.compute.amazonaws.com:5432/d50rgmkqi2ipus?schema=hello-prisma2" } ``` ### Use expressive variable names Good: ```ts const getUsers = (...) const deleteUsers = (...) ``` Bad: ```ts const results = (...) // Too generic const foo = (...) // Too vague ``` ### Include valid code snippets Ensure that code snippets you include are realistic examples that would work if run in the context presented. ### Follow Prisma Schema naming conventions When you create a Prisma Schema for an example, follow the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) we advise for users. ### List shell commands in a single code block When you need to provide a series of CLI commands as instructions to the reader, use a single block. Don't use a list unless you want to provide context for each step: #### Bad - `cd path/to/server` - `docker compose up -d --build` - `./node_modules/.bin/sequelize db:migrate` or `npx sequelize db:migrate` - `./node_modules/.bin/sequelize db:seed:all` or `npx sequelize db:seed:all` #### Better ```terminal cd path/to/server docker compose up -d --build ./node_modules/.bin/sequelize db:migrate # or `npx sequelize db:migrate` ./node_modules/.bin/sequelize db:seed:all # or `npx sequelize db:seed:all` ``` or 1. Navigate into the project directory: `cd path/to/server` 1. Start Docker containers: `docker compose up -d --build` 1. Migrate your database schema: `./node_modules/.bin/sequelize db:migrate` or `npx sequelize db:migrate` 1. Seed the database: `./node_modules/.bin/sequelize db:seed:all` or `npx sequelize db:seed:all` ### Don't prepend CLI commands in code blocks with `$` Use the `terminal` language meta string for CLI commands - this type of code block includes a `$`: ```` ```terminal npm install prisma ``` ```` For example: ```terminal npm install prisma ``` ### Use `npm` as the default package manager All examples should use `npm`. Other package manager options (`yarn`, `pnpm`, `bun`) should only be used if commands differ and never as the default. --- # Docs example data model URL: https://www.prisma.io/docs/about/style-guide/schema-models `User` and `Post` are the canonical models that we use in our examples throughout the Prisma docs. ## The `User` and `Post` data model We chose the `User` and `Post` models for the following reasons: - They do not require domain-specific knowledge. - They are commonly used as an example in the ORM space. This makes them familiar for users coming from other tools. - Consistent models make it easier for the reader when learning about different concepts, because there will be less context switching. - Less decision making and cognitive overhead for the docs authors. Using the same models reduces decision fatigue and is one less thing to worry about when trying to explain concepts. ## Naming conventions See the [naming conventions](/orm/reference/prisma-schema-reference#naming-conventions) for Prisma schemas. Use the following for table and column names: - Format table names in [PascalCase](https://en.wikipedia.org/wiki/PascalCase). - Format column names in [camelCase](https://en.wikipedia.org/wiki/Camel_case). ## Standard SQL Dialect Throughout the Prisma docs, PostgreSQL's dialect of SQL is used as the standard. If the context of a particular section requires specifying multiple dialects, those may be made available via the technology switcher component (`SwitchTech`) or tabbed code blocks (`TabbedContent`). --- # Prisma product and component names URL: https://www.prisma.io/docs/about/style-guide/prisma-product-names ## Use the following forms - The Prisma Data Platform (or just "PDP" - no definite article - after the first mention) - Prisma ORM - Prisma Client (not any variation of "the Client") - Prisma schema - Prisma Migrate - Prisma CLI - Prisma Studio - Prisma Accelerate Do not abbreviate any of these names, except where noted above. --- # Prisma docs image guidelines URL: https://www.prisma.io/docs/about/style-guide/image-guidelines ## Screenshots You can take screenshots with your favorite tool. We find it very easy to use SnagIt when you need to edit screenshots or add annotations to them. We suggest its use as a best practice. ### Style - Take focused screenshots of visible and legible areas of the UI. - Apply minimal styling to screenshots. Do not use unnecessary effects, annotations, or styles. - Exclude unnecessary UI areas and details. - Use full-screen screenshots only when needed. - Apply a centered shadow on the entire image canvas. If not, a screenshot with a white-background UI blends with the default white background of Prisma Docs. - In SnagIt, you can add a shadow with **Effects** > **Shadow** and configure its parameters as listed below. - Position: Centered - Color: Black - Opacity: 75% - Blur: 5pt :::info **Tip**

For larger and full-screen images, adjust the blur in the range of 7 - 10pt to make the shadow more visible on the page. ::: SnagIt - Screenshot canvas shadow ### Annotations If you can, avoid annotations. If necessary, apply annotations that are minimal and similar in style to the screenshot below. Data Browser - Save multiple changes For details, see the sections below. Again, we suggest the use of SnagIt as a best practice. #### Text annotations - Use **Helvetica Neue** font. - Use black font color. - Use a font size between 18 and 24 pt for text annotations. Adjust depending on the screenshot size. - The font size of annotations should not be much bigger than the text in the screenshot. - Apply a white outline on the text. This ensures that the black text will be visible in Dark mode. SnagIt - Screenshot text annotations #### Arrow and line annotations - Use black color for arrows or lines. - If you have text annotations that use arrows or lines to point to an area on the screenshot, a small part of the line or arrow should appear on the canvas (and outside of the screenshot). - Apply a centered shadow on each pointer and make the shadow color white. This ensures that the part of the line that is outside of the screenshot remains visible in Dark mode. SnagIt - Screenshot arrow line annotations ### File type and path - Save screenshots as `.png` files. - Save SnagIt project files in the same location and with the same filename, but with the newer cross-platform `.snagx` file extension. - Do not use the older, platform-specific file extensions (`.snag` on Windows, `.snagproj` on macOS). ### Filename - Keep filenames short and descriptive. - Use only alphanumeric characters. - Use relevant keywords in filenames for SEO purposes. - Use hyphens (`-`) to separate keywords. - Do not use spaces to separate keywords. ### Keywords in filenames - Use only meaningful keywords. - Do not use randomized characters in the filename. For example, `d0fjlsf81.png`. - At the beginning of filenames, use keywords that identify the UI context. - If applicable, follow with keywords that specify the action that you demonstrate in the screenshot. For example: `data-browser-select-model.png`. ### File location To decide where to save images, use the guidelines below. - Save screenshots shared between multiple pages in `content/doc-images/`. - If a page contains up to two images, save the screenshot files as peers to the MDX file. ```bash ... 06-image-guidelines.mdx ... snagit-arrow-line-config.png snagit-arrow-line-config.snagx snagit-text-annotation-config.png snagit-text-annotation-config.snagx ``` - If you need more than two images in an MDX file, create a peer `images/` directory and save the image files in it. ```bash ... 06-image-guidelines.mdx ... images/ 06-01-snagit-arrow-line-config.png 06-01-snagit-arrow-line-config.snagx 06-02-snagit-text-annotation-config.png 06-02-snagit-text-annotation-config.snagx ``` - At the beginning of each screenshot filename, add the number of the related MDX file. - After that, use sequential numbering to specify the sequence in which the images appear in the MDX file. ## Diagrams - Use [Figma](https://www.figma.com) to create diagrams. - For consistency, when you create a new diagram, base it on an existing one. - Add the URL of the source image to the Markdown page. Use a comment immediately above the image tag, as follows: ```md ![image](./trace-diagram.png) ``` ## Add images to MDX files For full-width images, use the shorter image MDX component:`![]()`. ```markdown ![Alt text](./peer-file.png) ``` If you need to shrink an image by width, use the `` component. ```html SnagIt - Screenshot text annotations ``` --- # User interface (GUI) guidelines URL: https://www.prisma.io/docs/about/style-guide/user-interace-guidelines ## Use numbered lists to document UI steps To document a complete task (such as _Create a new project_), use numbered lists to organize separate steps into a sequence of steps. - Use indented numbered lists to document substeps. - Avoid numbered lists that comprise more than 10 steps or steps that comprise more than 10 substeps. - If you have more than 10 steps or steps with more than 5-10 substeps, consider separating into multiple tasks. ## Write each step as a single action with a clear verb Each step (numbered item) must include a verb that guides the completion of the step. ```md The status changes to **Completed**. From **Status**, select **Completed**. ``` Make sure that steps are discrete and that their related verbs sound instructive. Do not put more than one action in a single step unless the step finishes with the action to confirm or cancel that involves the click of a specific button or UI control. ```md When you click **Invite Member** and the **Add member** pop-up opens, select the role for the new team member. 1. Click **Invite Member**. 2. In the **Add member** pop-up, select the role for the new team member and click **Invite**. ``` ## Document step results only for important outcomes If you need to describe the results of a step, separate them with a line break so that they appear indented on a new line under the step. ```md 1. Click **Invite Member**.
Your team member receives an email with a link to join the project. ``` Avoid the description of obvious results that happen when a user carries out a step. ```md 1. From the **Edit** menu, select **Copy**.
The text is copied to the clipboard. ``` ## Format the names of UI elements with bold Use bold for the names of all UI controls. | UI element | Example | | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | buttons | Click **Next**.
Click **Cancel**. | | radio buttons | Under **Payment method**, select **Wire transfer**. | | checkboxes | • Select **Include sample data**.
• Clear **Include sample data**. | | drop-down menus | • From **GitHub Accounts & Organizations**, select an account or organization.
• From **Static IPs**, select **Enabled**.
• From **Branch**, select the repository branch for this environment. | | links | Click **Learn more**. | | menu names | Click **File**. | | menu items | Select **Open**. | | menu cascades | Select **File** > **Save**. | | hamburger menu / three-dot menu | • Click the three-dot menu and select **Make default**.
• Click the hamburger menu and select **Make default**. | | tab | • Select the **macOS** tab.
• Click the **Network** tab. | | page | On the **Configure project** page, … | | window | In the **Payment information** pop-up window, enter the details for your payment method. | | screen/tab | On the **Data Browser** screen, select a record. | | pane/panel | In the **Configuration** panel, click **Network**. | | section | Under **Accelerate**, select **Enabled** from **Static IPs**. | ## Identify UI elements at the beginning of steps When you document an interaction with a UI element, begin steps with a reference to the name of the UI element to help readers navigate and scan the listed steps more easily. ```md 1. Enter a name for your project in **Display Name**. 2. Select a GitHub account or an organization from **GitHub Accounts & Organizations**. 3. Select **Create a repository**. 4. (Optional) Enter a name for the repository in **Repository Name**. 1. In **Display Name**, enter a name for your project. 2. From the **GitHub Accounts & Organizations** drop-down menu, select a GitHub account or an organization. 3. Select **Create a repository**. 4. (Optional) In **Repository Name**, enter a name for the repository. ``` ## Identify optional steps Add the text (Optional) at the beginning of optional steps. Do so even when they are written with an “If…” statement. ```md 1. (Optional) From **Static IPs**, select **Enabled** if your database is behind a firewall and you can only configure external access from specific IP addresses. Copy the IP addresses and add them to the allowlist of your database. 2. (Optional) If your database is behind a firewall and you can only configure external access from specific IP addresses, then from **Static IPs**, select **Enabled**. 1. If your database is behind a firewall and you can only configure external access from specific IP addresses, then from **Static IPs**, select **Enabled**. ``` ## Avoid excessive use of UI terminology It can feel excessive to include the UI term for each UI element when you write steps for interacting with UI. To make UI steps easier to read, in most cases you can omit the UI term for each UI element. ### Example 1: drop-down menu ```md From the **GitHub Accounts & Organizations** drop-down menu, select a GitHub account or an organization. From **GitHub Accounts & Organizations**, select a GitHub account or an organization. ``` ### Example 2: text box ```md In the **Display Name** text box, enter a name for your project. In **Display Name**, enter a name for your project. ``` ### Example 3: select the option ```md Select the **Create a repository** option. Select **Create a repository**. ``` ### Example 4: clear the checkbox ```md Deselect the **Include sample data** check box to skip seeding the database with sample data. Clear **Include sample data** to skip seeding the database with sample data. ``` In specific cases, calling out the UI control name brings clarity and makes it easy to document a more complex step. Use your judgement and avoid this rule in such cases. ```md - Under _Accelerate_, from **Location**, select the geographic location for Prisma Accelerate. - Under _Accelerate_ and from **Location**, select the geographic location for Prisma Accelerate. Under _Accelerate_, from the **Location** drop-down menu, select the geographic location for Prisma Accelerate. ``` ## Short and obvious steps In the middle or at the end of a procedure, the final step is sometimes very short and obvious for readers. - Click **Next**. - Click **OK**. - Click **Save**. - Click **Done**. Even if developer audiences do not need a reminder to save their files, specific cases exist in which omitting a short step can cause confusion. 1. Click **Delete** for the item you want to delete. 2. In the confirmation popup, enter the name of the item and click **Delete**. In other cases, short steps are not really necessary but still complete a valid procedure. One such example can be a **Done** button at the end of a wizard. Decide based on context if a short step adds noise or if it is a must to have it. ## Do not document requirements for input fields (text boxes) Text boxes or input fields in modern UIs typically provide immediate validation and feedback when users type in forbidden characters. Because of this, it is not necessary to list: - allowed characters - allowed text length ```md In **Display Name**, enter a name for your project. :::info **💡 Note**

Follow the rules below when you enter a display name for your project.

• Include at least one letter
• Keep the length up to 40 characters~~ ::: In **Display Name**, enter a name for your project. ``` ## Fall back to passive voice when the doer is difficult to identify In some cases, it is very difficult to identify the doer in a sentence or the doer sounds awkward to name. ```md The form automatically pre-fills the GitHub repository based on the project name you provide. In the repository name, the form replaces each space with a hyphen. The GitHub repository name is pre-filled based on the display name and each space is replaced with a hyphen. ``` ## Match capitalization of UI controls Document the user interface as it appears and do not alter UI text in the documentation to meet style guide or other requirements. For example, if a button has the text CANCEL, match the all-caps in the documentation. ```md Click **CANCEL**. Click **Cancel**. ``` --- # Boilerplate content URL: https://www.prisma.io/docs/about/style-guide/boilerplate-content You can use the following phrases and blocks of content as templates when you work on the docs. TBA: link to our docs template files (currently in Notion, but should probably be added to our style guide) ### To introduce a preview feature ````md To enable this feature, add `namedConstraints` to `previewFeatures` in your schema: ```prisma highlight=3;normal generator client { provider = "prisma-client-js" //highlight-next-line previewFeatures = ["namedConstraints"] } ``` ```` ### To make a recommendation If it is a recommendation made by Prisma, use: > "**We recommend that** you share a single instance of `PrismaClient` across your application." If it is an industry standard, use: > "**It is recommended practice to** limit the number of database connections to X." --- # Prisma docs style guide URL: https://www.prisma.io/docs/about/style-guide/index This guide contains guidelines for contributors to the Prisma docs. Its goal is to ensure consistency throughout the Prisma docs and with other official Prisma materials. --- # MDX components URL: https://www.prisma.io/docs/about/docs-components/mdx-examples This page describes how to use the custom [MDX](https://mdxjs.com/) components (e.g. code blocks) in the Prisma docs. Components not listed here are part of the [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features) ## `TopBlock` Required at the top of the page to avoid styling issues: ```md This page describes how to use [MDX](https://mdxjs.com/) components (e.g. code blocks) in the Prisma docs. Components not listed here are part of the [Docusaurus Markdown features](https://docusaurus.io/docs/markdown-features) ``` ## Code blocks Example: ```js async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` Code: ```` ```js async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` ```` ### Prisma schema Example: ```prisma datasource db { provider = "sqlite" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User? @relation(fields: [authorId], references: [id]) authorId Int? } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } ``` Code: ```` ```prisma datasource db { provider = "sqlite" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User? @relation(fields: [authorId], references: [id]) authorId Int? } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } ``` ```` ### Code block with file icon Example: ```prisma file=schema.prisma datasource db { provider = "sqlite" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User? @relation(fields: [authorId], references: [id]) authorId Int? } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } ``` Code: ```` ```prisma file=schema.prisma datasource db { provider = "sqlite" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User? @relation(fields: [authorId], references: [id]) authorId Int? } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } ``` ```` ### Code block with no copy option By default, all the code blocks will have a `copy` icon for copying the code. If you want to disable the `copy` option in the code block, please use `no-copy` property. Example: ```js no-copy async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` Code: ````no-copy ```js no-copy async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` ```` ### Code block without line numbers Example: ```js no-lines async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` Code: ```` ```js no-lines async function main() { const allUsers = await prisma.user.findMany() console.log(allUsers) } ``` ```` ### Terminal styled code block Example: ```terminal npm run dev ``` Code: ```` ```terminal npm run dev ``` ```` ### Code block wrapped For code blocks where we _don't_ want to have a scrollable box. Example with `wrap`: ```code wrap $ this is a single, really long line of code that shouldn't need to be scrollable to check what it says and simply wraps over to the next line, making it all visible in the same box ``` Example without `wrap`: ```code $ this is a single, really long line of code that shouldn't need to be scrollable to check what it says and simply wraps over to the next line, making it all visible in the same box ``` Code: ```` ```code wrap $ this is a single, really long line of code that shouldn't need to be scrollable to check what it says and simply wraps over to the next line, making it all visible in the same box ``` ```` ### Code block with highlighted code Example: ```js file=test.ts highlight=2;add|4;delete|6,7;edit|9-12;normal async function main() { added code deleted code edited code highlights over multiple lines can be done by using a hyphen } ``` Code: ```` ```js file=test.ts highlight=2;add|4;delete|6,7;edit|9-12;normal async function main() { added code deleted code edited code highlights over multiple lines can be done by using a hyphen }``` ```` ## Expand/Collapse section Example:
Expand if you want to view more Here's more!
```
Expand if you want to view more Here's more!
``` ## Code with result Example: ``` yarn prisma init ``` ```code no-copy wrap $ yarn prisma init yarn run v1.22.0 warning package.json: No license field $ /Users/janedoe/Desktop/tsdf/node_modules/.bin/prisma init ✔ Your Prisma schema was created at prisma/schema.prisma. You can now open it in your favorite editor. Next steps: 1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started. 2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql or sqlite. 3. Run `prisma db pull` to introspect your database schema and update the Prisma schema data models accordingly. 4. Run `prisma generate` to install Prisma Client. You can then start querying your database. More information in our documentation: https://pris.ly/d/getting-started ``` Code: ```` ``` yarn prisma init ``` ```code no-copy wrap $ yarn prisma init yarn run v1.22.0 warning package.json: No license field $ /Users/janedoe/Desktop/tsdf/node_modules/.bin/prisma init ✔ Your Prisma schema was created at prisma/schema.prisma. You can now open it in your favorite editor. Next steps: 1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started. 2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql or sqlite. 3. Run `prisma db pull` to introspect your database schema and update the Prisma schema data models accordingly. 4. Run `prisma generate` to install Prisma Client. You can then start querying your database. More information in our documentation: https://pris.ly/d/getting-started ``` ```` Example with custom output text ``` yarn prisma init ``` ```code no-copy wrap $ yarn prisma init yarn run v1.22.0 warning package.json: No license field $ /Users/janedoe/Desktop/tsdf/node_modules/.bin/prisma init ✔ Your Prisma schema was created at prisma/schema.prisma. You can now open it in your favorite editor. Next steps: 1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started. 2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql or sqlite. 3. Run `prisma db pull` to introspect your database schema and update the Prisma schema data models accordingly. 4. Run `prisma generate` to install Prisma Client. You can then start querying your database. More information in our documentation: https://pris.ly/d/getting-started ``` Code: ```` ``` yarn prisma init ``` ```code no-copy wrap $ yarn prisma init yarn run v1.22.0 warning package.json: No license field $ /Users/janedoe/Desktop/tsdf/node_modules/.bin/prisma init ✔ Your Prisma schema was created at prisma/schema.prisma. You can now open it in your favorite editor. Next steps: 1. Set the DATABASE_URL in the .env file to point to your existing database. If your database has no tables yet, read https://pris.ly/d/getting-started. 2. Set the provider of the datasource block in schema.prisma to match your database: postgresql, mysql or sqlite. 3. Run `prisma db pull` to introspect your database schema and update the Prisma schema data models accordingly. 4. Run `prisma generate` to install Prisma Client. You can then start querying your database. More information in our documentation: https://pris.ly/d/getting-started ``` ```` ## Parallel blocks Example: ```ts const posts = await postRepository.find({ where: { title: 'Hello World', }, }) ``` ```ts const posts = await postRepository.find({ where: { title: ILike('Hello World'), }, }) ``` Code: ```` ```ts const posts = await postRepository.find({ where: { title: 'Hello World', }, }) ``` ```ts const posts = await postRepository.find({ where: { title: ILike('Hello World'), }, }) ``` ```` --- # Front matter URL: https://www.prisma.io/docs/about/docs-components/frontmatter ## Meta information Front matter that informs the meta information of a page. ### `title` The `

` title of the page. This title appears at the top of the page, and in the left-hand navigation. You do not need to add this text as an `

` because Gatsby generates this heading from the `title` tag. Note: - You can wrap the `title` text in single quotes, but this is not mandatory. - If you wrap the `title` text in single quotes, then you cannot include apostrophes in the text. ### `metaTitle` The `` of the page - falls back to `title` (`h1`). This tag is important for Google SEO. If we wish, we can make the `metaTitle` more descriptive than the `title`. For good SEO, spell out abbreviations in this tag, unless they are industry standard. For example, spell out "Prisma Data Platform", but it is fine to use the abbreviation "ORM". Note: - You can wrap the `metaTitle` text in single quotes, but this is not mandatory. - If you wrap the `metaTitle` text in single quotes, then you cannot include apostrophes in the text. ## `sidebar_label` Specifies a different, usually shorter title for the left-hand navigation. ### `metaDescription` The `<meta name="description" content="" />` of the page. Note: - You can wrap the `metaDescription` text in single quotes, but this is not mandatory. - If you wrap the `metaDescription` text in single quotes, then you cannot include apostrophes in the text. ## Navigation (left sidebar) Front matter that configured the navigation. ### `duration` Accepts a string specifying the duration to read the article. Example: `duration: '15 min'` ### `preview` Accepts `true` or `false` (defaults to `false`). Adds a `Preview` label to a page in the left-hand navigation. ### `deprecated` Accepts `true` or `false` (defaults to `false`). Adds a `Deprecated` label to a page in the left-hand navigation. ## Table of Contents (right sidebar) ### `toc` Enable or disable table of contents navigation on the page (defaults to `false`). For example: ``` toc: true ``` ### `tocDepth` Controls the depth of headings to show in the in-page ToC: ``` tocDepth: 2 ``` > **Note**: Currently defaults up to level - `h2` ## Search Front matter that configures search. ### `search` Accepts `true` or `false` (defaults to `true`). When set to `false`, omits the page from search results. ``` search: false ``` ## Page content Front matter that configured page content ### `langSwitcher` Accepts an array of languages to be shown in the page as dropdown options in order to switch the context between the pages Example: ``` langSwitcher: ['typescript', 'node'] ``` ### `dbSwitcher` Accepts an array of database options to be shown in the page as dropdown options in order to switch the context between the pages Example: ``` dbSwitcher: ['postgresql', 'mysql', 'sqlserver', 'planetscale', 'cockroachdb'] ``` ## Design Front matter to configure the visual appearance of a page. ### `wide` Accepts `true` or `false` (defaults to `false`). When set to 'true', this page will have a content width of 988px instead of the default 748px. Example: ``` wide: true ``` Note: - Please use this only for pages with unreadable wide tables. --- # Prisma docs components URL: https://www.prisma.io/docs/about/docs-components/index ## In this section <Subsections depth="3" /> --- # Writing template URL: https://www.prisma.io/docs/about/template A short introduction that encourages visitors to read on. ## A section Break your page up into sections. Use the `toc_max_heading_level` front matter variable to determine how many levels the table of contents should have. ### A subsection If possible, avoid too many deeply nested subsections. --- # About URL: https://www.prisma.io/docs/about/index This section of our docs is about... the docs! Here we describe how our docs are made and how we would prefer you contribute. Here are some handy links: - [Our style guide](/about/style-guide) is a good place to start to learn about how we write our documentation and the tone we use. - [Our component guide](/about/docs-components) is great for understanding the React components that are available to you in our documentation. - [Our template](/about/template) is a starter template for a page of content. ## The `User` and `Post` data model `User` and `Post` are the canonical models that are being used throughout the Prisma docs. The `User` and `Post` models have been selected for the following reasons: - These two models do not require domain-specific knowledge. - They are also commonly used as an example in the ORM space, making them familiar for users coming from other tools. - Having consistent models makes it easier for the reader when learning about different concepts, since there will be less context switching. - Less decision making and cognitive overhead for the docs authors. Using the same models reduces decision fatigue and is one less thing to worry about when trying to explain concepts. ## Naming conventions for tables and columns Prisma ORM defaults to models (and therefore tables) formatted in [PascalCase](https://en.wikipedia.org/wiki/Camel_case) while fields (and therefore columns) are in [camelCase](https://en.wikipedia.org/wiki/Camel_case) ## Embrace redundancy Meet the user where they are. If a piece of information needs to be described in multiple places, do so, but be sure to use [a markdown fragment](https://docusaurus.io/docs/markdown-features/react#importing-markdown) so that information can be updated in one place in the future. <Subsections /> --- # Getting Started URL: https://www.prisma.io/docs/optimize/getting-started ## Prerequisites Before you begin with Prisma Optimize, ensure you have the following: - A [Prisma Data Platform account](https://console.prisma.io/optimize?utm_source=docs&utm_medium=optimize-page). - A project using [Prisma Client](/orm/prisma-client) version `5.0.0` or higher (we recommend using the latest version). - A PostgreSQL, MySQL/MariaDB, CockroachDB, or MS SQL Server database. :::note Prisma Optimize is intended for use in local environments. Learn more in the [FAQ](/optimize/faq#can-i-use-prisma-optimize-in-production). ::: ## 1. Launch Optimize 1. Log in to your [Prisma Data Platform account](https://console.prisma.io/optimize?utm_source=docs&utm_medium=optimize-page). 2. <a href="/docs/platform/about#accessing-the-optimize-dashboard" target="_blank">Follow the instructions</a> to access and launch Prisma Optimize. ## 2. Add Optimize to your application ### 2.1. Install the Optimize Prisma Client extension Install Prisma Client and the Optimize extension: ```bash npm install @prisma/client@latest @prisma/extension-optimize ``` <details> <summary>Enabling tracing in older versions of Prisma ORM</summary> For versions of Prisma ORM between `4.2.0` and `6.1.0`, you need to enable the `tracing` preview feature in your Prisma schema file. ```prisma generator client { provider = "prisma-client-js" previewFeatures = ["tracing"] } ``` </details> ### 2.2. Add the Optimize API Key to your `.env` file <a href="/docs/platform/about#generating-an-optimize-api-key" target="_blank">Generate a Prisma Optimize API key</a> and add it to your `.env` file: ```bash OPTIMIZE_API_KEY="YOUR_OPTIMIZE_API_KEY" ``` ### 2.3. Extend your Prisma Client instance Extend your existing Prisma Client instance with the Optimize extension: ```ts import { PrismaClient } from "@prisma/client"; import { withOptimize } from "@prisma/extension-optimize"; const prisma = new PrismaClient().$extends( withOptimize({ apiKey: process.env.OPTIMIZE_API_KEY }), ); ``` #### Using the Optimize extension with other extensions or middleware Since [extensions are applied one after another](/orm/prisma-client/client-extensions#conflicts-in-combined-extensions), make sure you apply them in the correct order. Extensions cannot share behavior and the last extension applied takes precedence. If you are using [Prisma Accelerate](/accelerate) in your application, make sure you apply it _after_ the Optimize extension. For example: ```ts const prisma = new PrismaClient().$extends(withOptimize()).$extends(withAccelerate()) ``` If you are using [Prisma Middleware](/orm/prisma-client/client-extensions/middleware) in your application, make sure they are added before any Prisma Client extensions (like Optimize). For example: ```ts const prisma = new PrismaClient().$use(middleware).$extends(withOptimize()) ``` ### 2.5. Use Prisma Optimize to generate insights Follow these steps to start generating query insights with Prisma Optimize: 1. In the Optimize dashboard, click the **Start recording** button, then run your app and execute some Prisma queries while recording is active. 2. After your app runs and generates insights based on the executed Prisma queries, click the **Stop recording** button. 3. Explore [individual query details](/optimize/recordings#data-captured-in-a-recording-session) by clicking on them, and check the **Recommendations** tab for any suggested improvements to enhance query performance. :::info Use [Prisma AI](/optimize/prisma-ai) to understand recommendations and apply them within your Prisma model context. ::: For a hands-on learning experience, try out the [step-by-step example](https://github.com/prisma/prisma-examples/tree/latest/optimize/starter). ## Need help? If you need assistance, reach out in the `#help-and-questions` channel on our [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=generated_text_cta), or connect with [our community](https://www.prisma.io/community) to see how others are using Optimize. --- # Recordings URL: https://www.prisma.io/docs/optimize/recordings The recordings feature helps developers debug and isolate sets of queries into distinct sessions, known as recordings. This targeted approach enables precise performance analysis and optimization by preventing the mixing of queries from different applications or test rounds, leading to clearer insights and more effective debugging. ## Managing a recording session You can manually start and stop recording sessions via the [Optimize dashboard](https://console.prisma.io/optimize) by clicking the **Start Recording** and **Stop Recording** buttons. :::warning A recording will automatically stop if the 10k query limit is reached or if the Prisma schema of the app is changed. ::: ## Identifying a recording session You can rename and tag your recording sessions for easy identification and context. Click on the default name of the session and type the desired name. ## Data captured in a recording session Each recording session captures detailed insights about the queries executed in your app, including: - All queries executed during the session. - The raw query generated and sent to the database by Prisma ORM as **Raw Query**. - The number of times a query pattern was executed, listed as **Count**. - [Query performance metrics](/optimize/performance-metrics). - Errors encountered during query execution. Each recording can include up to 10k queries. There are no limits on storage retention. ## Recommendations from a recording session When a recording session ends, Optimize generates recommendations such as: - [Excessive number of rows returned](/optimize/recommendations/excessive-number-of-rows-returned) - [Full table scans caused by LIKE operations](/optimize/recommendations/full-table-scans-caused-by-like-operations) - [Queries on unindexed columns](/optimize/recommendations/queries-on-unindexed-columns) - [Repeated query](/optimize/recommendations/repeated-query) - [Overfetching](/optimize/recommendations/select-returning) - [Using `@db.Money`](/optimize/recommendations/avoid-db-money) - [Using `@db.Char(n)`](/optimize/recommendations/avoid-char) - [Using `@db.VarChar(n)`](/optimize/recommendations/avoid-varchar) - [Using `timestamp(0)` or `timestamptz(0)`](/optimize/recommendations/avoid-timestamp-timestampz-0) - [Using `CURRENT_TIME`](/optimize/recommendations/current-time) - [Storing large objects or BLOBs in the database](/optimize/recommendations/storing-blob-in-database) - [Indexing on unique columns](/optimize/recommendations/indexing-on-unique-columns) - [Long-running transactions](/optimize/recommendations/long-running-transactions) - [Unnecessary indexes](/optimize/recommendations/unnecessary-indexes) :::info Use [Prisma AI](/optimize/prisma-ai) to ask follow-up questions about a recommendation. ::: Learn more about the recommendations generated by Optimize [here](/optimize/recommendations). --- # Excessive number of rows returned URL: https://www.prisma.io/docs/optimize/recommendations/excessive-number-of-rows-returned Optimize provides recommendations to help you identify and resolve performance issues caused by excessive number of rows returned from a query. The following query targeting a `User` model does not provide a [`take` option](/orm/reference/prisma-client-reference#findmany): ```ts await prisma.user.findMany({ where: { email: "janedoe@gmail.com" }}) ``` ## What is the problem? When a query is executed without specifying a limit, it will return all relevant rows, which can lead to several issues: ### User experience - **Viewing data:** Users typically need only a portion of the data at any given time, not all of it at once. - **Impact on the user's device:** Displaying all the data at once can strain the user's device resources. For example, loading thousands of rows in a web application can slow down or freeze the browser, consuming significant memory and CPU resources. - **Waiting time:** Retrieving a large number of rows can significantly increase the time it takes to get the data from the database to the user's device. ### Resource Utilization - **Unnecessary data load:** Processing more data than required wastes valuable resources. - **Memory usage:** Excessive memory consumption can lead to inefficiency and, in severe cases, cause the system to run out of memory, disrupting the service. --- # Using CURRENT_TIME URL: https://www.prisma.io/docs/optimize/recommendations/current-time The following raw SQL query uses the `CURRENT_TIME` function: ```ts prisma.$queryRaw`SELECT CURRENT_TIME;` ``` ### Why this is a problem The `CURRENT_TIME` keyword returns only the time (e.g., 14:30:00) without a date, making it unsuitable for tasks like logging or generating timestamps that require precise event tracking. It returns a value of type `timetz`, which was added for SQL standard compatibility but is generally discouraged. --- # Unnecessary indexes URL: https://www.prisma.io/docs/optimize/recommendations/unnecessary-indexes Optimize detects unnecessary indexes and recommends removing them to improve database performance. ### Why this is a problem Indexes enhance database query performance but can harm efficiency when overused. They consume storage and add overhead to `INSERT`, `UPDATE`, and `DELETE` operations. Unnecessary indexes can result in: - **Increased write costs:** Extra indexes slow down write operations. - **Higher storage use:** Unused indexes waste storage space. - **Query optimizer confusion:** Redundant indexes may cause inefficient query plans. Removing unnecessary indexes improves performance and simplifies maintenance. --- # Long-running transactions URL: https://www.prisma.io/docs/optimize/recommendations/long-running-transactions Optimize provides actionable recommendations to help you identify and resolve performance issues caused by **long-running transactions**. **Long-running transactions** can negatively impact scalability and resilience by locking resources and holding database connections for extended periods. Below is a common example of a problematic long-running transaction: ```ts // Example: A single massive transaction performing multiple steps await prisma.$transaction(async (prisma) => { const order = await prisma.order.create({ data: { /* ... */ }, }); await prisma.user.update({ where: { id: userId }, data: { balance: { decrement: order.total } }, }); await prisma.shipping.create({ data: { orderId: order.id /* ... */ } }); // Additional dependent operations }); ``` ### What is the problem? Long-running transactions can cause several critical issues that harm the performance and reliability of your application: - **Database locks**: Long transactions hold locks on rows, tables, or other resources, preventing access by other queries. This leads to contention and blocking, which can significantly disrupt concurrent operations. - **Connection tie-ups**: Transactions occupy database connections for their entire duration. With a limited connection pool, this can quickly exhaust available connections, resulting in application-wide slowdowns or failures. - **Increased contention**: As locks accumulate and connections are tied up, other transactions queue up, creating bottlenecks, higher latency, and reduced throughput. - **Scalability challenges**: Inefficiencies caused by long transactions are magnified in high-traffic systems, limiting the system’s ability to scale effectively. - **Fragility**: When a long transaction fails or times out, all intermediate progress is lost. This is especially problematic in workflows with multiple dependent steps, as recovering from partial failures becomes complex and error-prone. - **Debugging difficulties**: Troubleshooting long-running transactions is challenging due to their multiple steps and potential failures caused by timeouts, deadlocks, or unexpected dependencies. --- # Indexing on unique columns URL: https://www.prisma.io/docs/optimize/recommendations/indexing-on-unique-columns Optimize identifies redundant indexing on unique columns and provides recommendations for better database performance. ### Why this is an issue Unique constraints inherently enforce uniqueness by generating an underlying index. Adding an additional index to the same column is unnecessary and can lead to extra overhead. This redundancy increases write costs and slows down updates, as the database must synchronize multiple indexes. This guideline applies broadly to relational databases like PostgreSQL, MySQL, MariaDB, SQLite, and SQL Server, which automatically create indexes for unique constraints. --- # Storing large objects or BLOBs in the database URL: https://www.prisma.io/docs/optimize/recommendations/storing-blob-in-database Optimize provides recommendations to help identify and resolve performance issues caused by storing large objects in the database. It also suggests alternative approaches to mitigate these challenges. The following model uses the `Bytes` type: ```prisma model User { id Int @id @default(autoincrement()) name String? // Storing raw image data directly in the database avatarBytes Bytes? } ``` ## What is the problem? Storing large binary objects (such as images) in the database can lead to several challenges: - **Excessive storage usage**: Large objects occupy significant space in the database, complicating management. - **Increased I/O load**: Handling large objects adds strain to the database's input/output operations. - **Slower query performance**: Most traditional databases are not optimized for efficiently serving large binary content, resulting in performance degradation during queries or updates. Moreover, storing large objects directly in the database can cause backups to become disproportionately large, increasing the time required for restoration processes. Serving these files through the database also creates a performance bottleneck, particularly under high traffic or frequent access scenarios. --- # Queries on unindexed columns URL: https://www.prisma.io/docs/optimize/recommendations/queries-on-unindexed-columns Optimize provides recommendations to help you identify and resolve performance issues caused by missing database indexes. The following queries targeting the `User` model use a [`where` property](/orm/prisma-client/queries/filtering-and-sorting) to filter on columns that do not have indexes: ```ts await prisma.user.findFirst({ where: { name: "Marc" } }) await prisma.user.findFirst({ where: { name: "Jon" } }) await prisma.user.count({ where: { name: "Nikolas" } }) ``` ## What is the problem? An index allows the database to retrieve data more quickly, similar to how an index in a book helps you locate information without reading every page. When using Prisma with a `where` property, if no indexes are defined for the relevant columns, the database may need to scan every row in the table (a *“full table scan”*) to find matches. This can be undesirable for several reasons: ### User experience For large datasets, if the database must scan the entire table to find matching rows, users will experience longer waiting times. ### Resource utilization - **High CPU usage:** Scanning large tables can significantly increase CPU usage, degrading overall system performance. - **Memory consumption:** More memory is required to process and store data during a full table scan. - **Disk I/O:** Full table scans increase disk input/output operations, potentially slowing down other database activities. :::warning While these issues might not appear in development due to smaller datasets, they can become *significant* problems in production, where datasets are typically much larger. ::: ## More on database indexes ### How indexes work Indexes create a data structure that stores the indexed column's values along with pointers to the corresponding rows in the table. When you query the database using an indexed column, the database can use this index to quickly locate the relevant rows instead of scanning the entire table. ### The trade-offs of indexing - **Space vs. time:** Indexing requires additional storage space to save index data, but it significantly speeds up data retrieval. - **Update overhead:** Every time data is added to, updated in, or removed from your table, there is an overhead to keep the indexes up to date, which can slow down write operations. ### When to use indexes - **Large datasets:** Indexes are particularly beneficial for tables with a large number of rows. - **Frequent queries with filtering or sorting:** Use indexes on columns that are frequently used for [filtering or sorting](/orm/prisma-client/queries/filtering-and-sorting#filtering). - **Looking up related data:** Use indexes on foreign key columns to speed up the retrieval of related records, such as when using [`include`](/orm/prisma-client/queries/relation-queries#include-a-relation). ### When not to use indexes - **Small tables:** For tables with very few rows, the overhead of maintaining indexes might not be worth the performance gain. - **Write-heavy tables:** Indexes can slow down write operations (`create`, `update`, `delete`) because the index needs to be updated as well. Avoid excessive indexing on models with frequent write operations. - **Infrequently accessed tables:** If a table is rarely accessed, the benefits of indexing may not justify the overhead. - **Columns with large data:** Indexing columns with large data can lead to higher storage requirements and might not provide significant performance improvements. - **Rarely filtered columns:** If a table is often accessed but rarely filtered by a specific column, creating an index on that column may not be beneficial. :::warning Even if you index a column, the database may not always use it. Many database management systems, such as PostgreSQL and MySQL, have a *query optimizer* that evaluates multiple execution plans and selects the one it estimates to be most efficient. In some cases, this may involve ignoring an existing index in favor of a different execution plan that it determines will perform better for that specific query. ::: --- # Full table scans caused by LIKE operations URL: https://www.prisma.io/docs/optimize/recommendations/full-table-scans-caused-by-like-operations Optimize provides recommendations to help you identify and resolve performance issues caused by full table scans from `LIKE` operations. The following query targeting the `User` model provides `contains` and `endsWith` as options, which translate to `LIKE` and `ILIKE` SQL operators. ```jsx await prisma.user.findMany({ where: { email: { contains: "gmail.com" }, name: { endsWith: "Burk" } } }) ``` ## What is the problem? `LIKE` and `ILIKE` operators in SQL can lead to full table scans, potentially impacting performance, especially with larger datasets: ### UX - **Slower load times:** Full table scans can significantly increase the time it takes to retrieve data, leading to longer wait times for users. ### Resource utilization - **Increased resource usage:** Full table scans increase CPU, memory usage, and disk I/O, straining system resources for your database. - **Increased costs:** In serverless database pricing plans, more intensive resource usage can translate into higher costs. --- # Repeated query URL: https://www.prisma.io/docs/optimize/recommendations/repeated-query Optimize provides recommendations to help you identify and resolve performance issues caused by repeated queries. The following query targeting the `Post` model is executed repeatedly with identical parameters: ```ts await prisma.post.findMany({ where: { published: true }, take: 20 }) ``` ### What is the problem? When the same query is executed multiple times with the same parameters within a short time frame, it can lead to: - **Time waste:** A new connection may be established between the application and database, the query and its parameters are sent to the database, the database processes the query, and the results are sent back to the application. - **Increased resource usage:** Query execution increases CPU and memory usage, as well as disk I/O, putting strain on your database's system resources. - **Higher costs:** In serverless database pricing models, higher resource usage can result in increased costs. :::info To learn more about avoiding repeated queries with caching using Prisma Accelerate, refer to the [Prisma Accelerate documentation](/accelerate/caching). ::: --- # Overfetching URL: https://www.prisma.io/docs/optimize/recommendations/select-returning Optimize provides recommendations to help you identify and resolve performance issues caused by over-fetched data. The following query might be overfetching data in queries on the `User` model: ```ts await prisma.user.findMany({ where: { email: { contains: "gmail" }, }, include: { links: true, }, }); ``` ## What is the problem? Retrieving data from all columns of a table, especially in large tables or those with complex relationships, can result in: - **Increased load times**: Fetching more data than necessary prolongs query processing and data transfer times. - **Greater resource consumption**: Retrieving unnecessary fields places strain on memory and CPU resources, both in the database and on the machines running your application. - **Higher costs**: Reading and transferring excess data can lead to increased processing costs. - **Security risks**: You might unintentionally expose sensitive data that should remain within the database. --- # Using @db.Money URL: https://www.prisma.io/docs/optimize/recommendations/avoid-db-money Optimize provides recommendations to help you identify and resolve performance issues caused by the use of `@db.Money` type. The following model uses the `@db.Money` native type: ```prisma model Item { // ... price Decimal @db.Money // ... } ``` ## What is the problem? The `@db.Money` data type in PostgreSQL is not ideal for storing monetary values. Internally, `@db.Money` is implemented as an integer, which offers speed but lacks flexibility. It handles fractional values and rounding in unexpected ways, which can lead to inaccuracies. Additionally, the `@db.Money` type does not store any information about the associated currency. Instead, it relies on the global `lc_monetary` locale setting, which may not be suitable for all use cases. For more information, refer to the [PostgreSQL documentation](https://wiki.postgresql.org/wiki/Don't_Do_This#Don.27t_use_money). --- # Using @db.Char(n) URL: https://www.prisma.io/docs/optimize/recommendations/avoid-char Optimize provides recommendations to help you identify and resolve performance issues caused by the use of `@db.Char(n)` type in PostgreSQL. In the following example, the `@db.Char(n)` native type has been used within the `Item` model on the `name` field: ```prisma model Item { // ... name String @db.Char(1) // ... } ``` ### Why this is a problem The `@db.Char(n)` type enforces a fixed length of `n`, which can cause unexpected issues in production if not properly managed by the application. In PostgreSQL, `char(n)` pads shorter values with spaces, leading to problems during comparisons and other operations. Unlike some databases that optimize `char(n)`, PostgreSQL does not offer such optimizations, making careful handling essential. --- # Using @db.VarChar(n) URL: https://www.prisma.io/docs/optimize/recommendations/avoid-varchar Optimize provides recommendations to help you identify and resolve performance issues caused by the use of `@db.VarChar(n)` type in PostgreSQL. The `@db.VarChar(n)` native type has been used within the `Item` model on the name field: ```prisma model Item { // ... name String @db.VarChar(1) // ... } ``` ### Why this is a problem The `@db.VarChar(n)` type restricts content to a maximum length of `n`, which can cause unexpected issues in production if not properly managed by the application. In PostgreSQL, `varchar(n)` performs the same as `text`, and no additional optimizations are provided for `varchar(n)`, making the choice between them more about convention than performance. --- # Using timestamp(0) or timestamptz(0) URL: https://www.prisma.io/docs/optimize/recommendations/avoid-timestamp-timestampz-0 Optimize provides recommendations to help you identify and resolve performance issues caused by the use of `@db.Timestamp(0)` and `@db.Timestamptz(0)` native types in PostgreSQL. The `@db.Timestamp(0)` and `@db.Timestamptz(0)` native types have been used within the following `User` model: ```prisma model User { // ... date DateTime @db.Timestamp(0) deletedAt DateTime @db.Timestamptz(0) // ... } ``` ### Why this is a problem When using a `@db.Timestamp(n)` or `@db.Timestamptz(n)` column with a precision of `0`, the database rounds the time to the nearest whole second, which can lead to unexpected results. For example, if you insert the current time, such as `15:30:45.678`, into a column with this precision, it will round up to `15:30:46`. This behavior can cause the recorded time to appear up to half a second in the future compared to the original time, which may be surprising when precise time accuracy is critical. --- # Recommendations URL: https://www.prisma.io/docs/optimize/recommendations/index Optimize provides recommendations focused on performance improvements such as indexing issues, excessive data retrieval, and inefficient query patterns. Recommendations include: :::info Use [Prisma AI](/optimize/prisma-ai) to ask follow-up questions about any recommendation. ::: <Subsections depth="3" /> --- # Prisma AI URL: https://www.prisma.io/docs/optimize/prisma-ai Prisma AI enables you to ask follow-up questions on a provided [recommendation](/optimize/recommendations) for additional clarity. ## Using the Prisma AI To interact with the Prisma AI: 1. Select a recommendation from an Optimize [recording](/optimize/recordings). 2. Click the **Ask AI** button. Prisma AI helps you gain deeper insights into a recommendation and learn how to apply it effectively to your Prisma model. --- # Performance metrics URL: https://www.prisma.io/docs/optimize/performance-metrics An Optimize recording session provides detailed insights into the latencies of executed queries, capturing key metrics such as average duration, 50th percentile, 99th percentile, and maximal query execution time. ## Total query durations Prisma Optimize measures total latency for query patterns, enabling you to analyze and debug slow queries effectively. ### Average query duration (**`AVG`**) The average query duration reveals the mean execution time across all queries, helping you assess overall performance trends and identify inefficiencies that impact the user experience. ### 50th percentile (**`P50`**) The 50th percentile, or median, query duration indicates the time within which half of your queries complete. This metric offers a clear view of typical user performance, unaffected by outliers. ### 99th percentile (**`P99`**) The 99th percentile query duration highlights the execution time for the slowest 1% of queries. This metric is crucial for uncovering and addressing performance bottlenecks that, while infrequent, can significantly impact user satisfaction. ### Maximal query duration (**`MAX`**) The maximal query duration measures the time taken by the single slowest query. This metric helps identify extreme cases, providing insights into the worst performance scenarios your system might face, so you can diagnose and resolve outliers. --- # FAQ URL: https://www.prisma.io/docs/optimize/faq ## Does Optimize automatically implement optimizations? Prisma Optimize offers insights and recommendations on how to improve your database queries. It does not alter any existing queries or your Prisma schema. ## How long is a recording session retained in Optimize? There are no limits on the storage retention period. Optimize will store a recording session until you explicitly delete it. ## Do recommendation limits reset monthly? Yes, the recommendation usage resets at the beginning of each calendar month. For example, if you use 5 recommendations by the end of the month, your usage will reset to 0 at the start of the next month. ## Can I get charged for exceeding the recommendation limit on the starter plan? Yes, if you’re on the starter plan, exceeding 5 recommendations in a billing cycle will result in a $5 charge at the end of that cycle. For more information, visit [our pricing page](https://www.prisma.io/pricing#optimize). ## How does Optimize track viewed recommendations for billing? Are they counted based on generated or viewed recommendations? They are counted based on viewed recommendations. Once you click on a recommendation from the recommendations table and view the recommendation's detail page, it counts as being seen. ## Can I use Prisma Optimize in production? No, Prisma Optimize is not intended for production use. It is specifically designed for local development, providing valuable insights and optimizations during that phase. While it’s technically possible to run it in a production environment, doing so could result in performance problems or unexpected behaviors, as Optimize is not built to handle the complexity and scale of production workloads. For the best experience, we recommend using Prisma Optimize solely in your development environment. You can use the `enable` property in the Optimize extension to run Optimize only in development environment. By default, the `enable` property is set to `true`. ```ts file=script.ts copy showLineNumbers import { PrismaClient } from '@prisma/client' import { withOptimize } from "@prisma/extension-optimize" const prisma = new PrismaClient().$extends( withOptimize({ apiKey: process.env.OPTIMIZE_API_KEY, enable: process.env.ENVIRONMENT === 'development', }) ); ``` --- # Known limitations URL: https://www.prisma.io/docs/optimize/known-limitations Below are the known limitations when using Prisma Optimize. If you are aware of any limitations that are missing, please let us know on the `#help-and-questions` channel in our community [Discord](https://pris.ly/discord?utm_source=docs&utm_medium=intro_text). ## Query limit on a recording session Each [recording session](/optimize/recordings) can contain a maximum of 10,000 queries. Once this limit is reached, the recording session will end. ## Recording limit per workspace Each [workspace](/platform/about#workspace) can contain a maximum of 100 [recordings](/optimize/recordings). ## Scope and constraints for the Prisma AI While [Prisma AI](/optimize/prisma-ai) can provide helpful guidance to implement a [recommendation](/optimize/recommendations), there are some important limitations to keep in mind: - **Information and accuracy**: The AI provides advice based on a broad, general knowledge base and does not have direct access to Prisma ORM documentation. This may occasionally result in inaccuracies or outdated information. - **Limited context and adaptation**: The AI does not persist conversations or learn from previous interactions. Its responses are generalized and may not always address the specific needs of advanced users. - **Static knowledge and scope**: The AI's knowledge is static and may not include recent updates or best practices after a certain date. It provides advice only within the context of Prisma ORM and cannot modify or execute code, nor interact directly with user environments. ## Using Prisma Accelerate client extension with the Optimize extension When using the [Optimize client extension](https://www.npmjs.com/package/@prisma/extension-optimize) with the [Accelerate client extension](https://www.npmjs.com/package/@prisma/extension-accelerate), ensure the Accelerate client extension is added last to your extended `PrismaClient`. This allows cacheable operations to be received by Optimize. ```ts const prisma = new PrismaClient() .$extends( withOptimize({ apiKey: process.env.OPTIMIZE_API_KEY, }), ) .$extends(withAccelerate()); ``` ### SQL references in MongoDB recommendations Prisma Optimize provides helpful recommendations for MongoDB users, though some explanations from [Prisma AI](/optimize/prisma-ai) may reference SQL-specific concepts. However, the [recommendations](/optimize/recommendations) remain useful and applicable to MongoDB environments. ### Raw query visibility in MongoDB Raw queries are visible in MongoDB, though the parameters passed to them are not displayed. ## Driver adapter compatibility Prisma Optimize is not yet compatible with [driver adapters](/orm/overview/databases/database-drivers#driver-adapters). However, as a workaround, you can run your queries locally using the regular Prisma Client along with Prisma Optimize to inspect and improve query performance. --- import { Bolt, BorderBox, BoxTitle, Database, Grid, LinkCard, List, SignalStream, SquareLogo, } from '@site/src/components/GettingStarted'; import { IconTitle } from '@site/src/components/shortcodes/index'; <IconTitle heading="h1" icon="fa-solid fa-magnifying-glass-chart" iconColor="#16A394" >Prisma Optimize</IconTitle> [Prisma Optimize](https://www.prisma.io/optimize?utm_source=docs). helps you generate insights and provides recommendations that can help you make your database queries faster. This helps you to: - Generate insights about your database queries - Identify errors to help debug your database queries - Receive recommendations and discuss them with an AI assistant to enhance query performance. Optimize aims to help developers of all skill levels write efficient database queries, reducing database load and making applications more responsive. <Grid> <LinkCard icon="fa-solid fa-arrow-right" title="Get started" desc="Start analyzing the prisma queries in your app in 5 minutes." link="/optimize/getting-started" /> <LinkCard icon="fa-brands fa-github" title="Examples" desc="Explore our ready-to-run examples using Optimize." link="https://github.com/prisma/prisma-examples?tab=readme-ov-file#prisma-optimize" /> </Grid> ## Supported databases Optimize works with the database you already have. <List framed> <SquareLogo url="/optimize/getting-started" image={'/img/technologies/postgresqlsimple.svg'} tech="PostgreSQL" /> <SquareLogo url="/optimize/getting-started" image={'/img/technologies/mysqlsimple.svg'} tech="MySQL" /> <SquareLogo url="/optimize/getting-started" image={'/img/technologies/mariadb.svg'} imageDark={'/img/technologies/mariadbdark.svg'} tech="MariaDB" /> <SquareLogo url="/optimize/getting-started" image={'/img/technologies/cockroachdbdark.svg'} tech="CockroachDB" /> <SquareLogo url="/optimize/getting-started" image={'/img/technologies/sqlserver.svg'} tech="MS SQL Server" /> </List> ## In this section <Subsections depth="3" /> --- # Migrate data using the expand and contract pattern URL: https://www.prisma.io/docs/guides/data-migration ## Introduction When making changes to your database schema in production, it's crucial to ensure data consistency and avoid downtime. This guide shows you how to use the expand and contract pattern to safely migrate data between columns. We'll walk through a practical example of replacing a boolean field with an enum field while preserving existing data. ## Prerequisites Before starting this guide, make sure you have: - Node.js installed (version 18 or higher) - A Prisma ORM project with an existing schema - A supported database (PostgreSQL, MySQL, SQLite, SQL Server, etc.) - Access to both development and production databases - Basic understanding of Git branching - Basic familiarity with TypeScript ## 1. Set up your environment ### 1.1. Review initial schema Start with a basic schema containing a Post model: ```prisma generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) } ``` ### 1.2. Create a development branch Create a new branch for your changes: ```bash git checkout -b create-status-field ``` ## 2. Expand the schema ### 2.1. Add new column Update your schema to add the new Status enum and field: ```prisma model Post { id Int @id @default(autoincrement()) title String content String? published Boolean? @default(false) status Status @default(Unknown) } enum Status { Unknown Draft InProgress InReview Published } ``` ### 2.2. Create migration Generate the migration: ```bash npx prisma migrate dev --name add-status-column ``` ## 3. Migrate the data ### 3.1. Create migration script Create a new TypeScript file for the data migration: ```typescript import { PrismaClient } from '@prisma/client' const prisma = new PrismaClient() async function main() { await prisma.$transaction(async (tx) => { const posts = await tx.post.findMany() for (const post of posts) { await tx.post.update({ where: { id: post.id }, data: { status: post.published ? 'Published' : 'Unknown', }, }) } }) } main() .catch(async (e) => { console.error(e) process.exit(1) }) .finally(async () => await prisma.$disconnect()) ``` ### 3.2. Set up migration script Add the migration script to your package.json: ```json { "scripts": { "data-migration:add-status-column": "tsx ./prisma/migrations/<migration-timestamp>/data-migration.ts" } } ``` ### 3.3. Execute migration 1. Update your DATABASE_URL to point to the production database 2. Run the migration script: ```bash npm run data-migration:add-status-column ``` ## 4. Contract the schema ### 4.1. Create cleanup branch Create a new branch for removing the old column: ```bash git checkout -b drop-published-column ``` ### 4.2. Remove old column Update your schema to remove the published field: ```prisma model Post { id Int @id @default(autoincrement()) title String content String? status Status @default(Unknown) } enum Status { Draft InProgress InReview Published } ``` ### 4.3. Generate cleanup migration Create and run the final migration: ```bash npx prisma migrate dev --name drop-published-column ``` ## 5. Deploy to production ### 5.1. Set up deployment Add the following command to your CI/CD pipeline: ```bash npx prisma migrate deploy ``` ### 5.2. Monitor deployment Watch for any errors in your logs and monitor your application's behavior after deployment. ## Troubleshooting ### Common issues and solutions 1. **Migration fails due to missing default** - Ensure you've added a proper default value - Check that all existing records can be migrated 2. **Data loss prevention** - Always backup your database before running migrations - Test migrations on a copy of production data first 3. **Transaction rollback** - If the data migration fails, the transaction will automatically rollback - Fix any errors and retry the migration ## Next steps Now that you've completed your first expand and contract migration, you can: - Learn more about [Prisma Migrate](/orm/prisma-migrate) - Explore [schema prototyping](/orm/prisma-migrate/workflows/prototyping-your-schema) - Understand [customizing migrations](/orm/prisma-migrate/workflows/customizing-migrations) For more information: - [Expand and Contract Pattern Documentation](https://www.prisma.io/dataguide/types/relational/expand-and-contract-pattern) - [Prisma Migrate Workflows](/orm/prisma-migrate/workflows) --- # How to manage schema changes in a team URL: https://www.prisma.io/docs/guides/implementing-schema-changes ## Introduction When working in a team, managing database schema changes can be challenging. This guide shows you how to effectively collaborate on schema changes using Prisma Migrate, ensuring that all team members can safely contribute to and incorporate schema changes. ## Prerequisites Before starting this guide, make sure you have: - Node.js installed (version 18 or higher) - A Prisma project set up with migrations - A relational database (PostgreSQL, MySQL, SQLite, SQL Server, etc.) - Basic understanding of Git - Basic familiarity with Prisma Migrate :::warning This guide **does not apply for MongoDB**.<br /> Instead of `migrate dev`, [`db push`](/orm/prisma-migrate/workflows/prototyping-your-schema) is used for [MongoDB](/orm/overview/databases/mongodb). ::: ## 1. Understand migration basics ### 1.1. Migration order Migrations are **applied in the same order as they were created**. The creation date is part of the migration subfolder name - for example, `20210316081837-updated-fields` was created on `2021-03-16-08:18:37`. ### 1.2. Source control requirements You should commit the following files to source control: - The contents of the `.prisma/migrations` folder, including the `migration_lock.toml` file - The Prisma Schema (`schema.prisma`) Source-controlling the `schema.prisma` file is not enough - you must include your migration history because: - Customized migrations contain information that cannot be represented in the Prisma schema - The `prisma migrate deploy` command only runs migration files ## 2. Incorporate team changes ### 2.1. Pull latest changes To incorporate changes from collaborators: 1. Pull the changed Prisma schema and `./prisma/migrations` folder 2. Run the migrate command: ```terminal npx prisma migrate dev ``` ### 2.2. Example scenario Let's walk through a sample scenario with three developers sharing schema changes: <TabbedContent code> <TabItem value="Before"> ```prisma file=schema.prisma model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User? @relation(fields: [authorId], references: [id]) authorId Int? } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } ``` </TabItem> <TabItem value="After"> ```prisma file=schema.prisma model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User? @relation(fields: [authorId], references: [id]) authorId Int? } model User { id Int @id @default(autoincrement()) email String @unique name String? //add-start favoriteColor String? // Added by Ania bestPacmanScore Int? // Added by you //add-end posts Post[] } //add-start // Added by Javier model Tag { tagName String @id tagCategory Category } //add-end ``` </TabItem> </TabbedContent> ## 3. Handle concurrent changes ### 3.1. Developer A's changes Ania adds a new field: ```prisma model User { /* ... */ favoriteColor String? } ``` And generates a migration: ```terminal npx prisma migrate dev --name new-field ``` ### 3.2. Developer B's changes Javier adds a new model: ```prisma model Tag { tagName String @id tagCategory Category } ``` And generates a migration: ```terminal npx prisma migrate dev --name new-model ``` ### 3.3. Merge changes The migration history now has two new migrations: ![A diagram showing changes by two separate developers converging in a single migration history.](/img/guides/migrate-team-dev.png) ## 4. Integrate your changes ### 4.1. Pull team changes 1. Pull the most recent changes: - Two new migrations - Updated schema file 2. Review the merged schema: ```prisma model User { /* ... */ favoriteColor String? bestPacmanScore Int? } model Tag { tagName String @id tagCategory Category posts Post[] } ``` ### 4.2. Generate your migration Run the migrate command: ```terminal npx prisma migrate dev ``` This will: 1. Apply your team's migrations 2. Create a new migration for your changes 3. Apply your new migration ### 4.3. Commit changes Commit: - The merged `schema.prisma` - Your new migration file ## Next steps Now that you understand team schema management, you can: - Learn about [customizing migrations](/orm/prisma-migrate/workflows/customizing-migrations) - Explore [deployment workflows](/orm/prisma-migrate/workflows/development-and-production) For more information: - [Prisma Migrate documentation](/orm/prisma-migrate) - [Team development workflows](/orm/prisma-migrate/workflows/team-development) --- # How to migrate from TypeORM to Prisma ORM URL: https://www.prisma.io/docs/guides/migrate-from-typeorm ## Introduction This guide shows you how to migrate your application from TypeORM to Prisma ORM. We'll use an extended version of the [TypeORM Express example](https://github.com/typeorm/typescript-express-example/) as a [sample project](https://github.com/prisma/migrate-from-typeorm-to-prisma) to demonstrate the migration steps. This migration guide uses PostgreSQL as the example database, but it equally applies to any other relational database that's [supported by Prisma ORM](/orm/reference/supported-databases). You can learn how Prisma ORM compares to TypeORM on the [Prisma ORM vs TypeORM](/orm/more/comparisons/prisma-and-typeorm) page. ## Prerequisites Before starting this guide, make sure you have: - A TypeORM project you want to migrate - Node.js installed (version 16 or higher) - PostgreSQL or another supported database - Basic familiarity with TypeORM and Express.js ## 2. Prepare for migration ### 2.1. Understand the migration process The steps for migrating from TypeORM to Prisma ORM are always the same, no matter what kind of application or API layer you're building: 1. Install the Prisma CLI 2. Introspect your database 3. Create a baseline migration 4. Install Prisma Client 5. Gradually replace your TypeORM queries with Prisma Client These steps apply whether you're building a REST API (e.g., with Express, Koa, or NestJS), a GraphQL API (e.g., with Apollo Server, TypeGraphQL, or Nexus), or any other kind of application that uses TypeORM for database access. ### 2.2. Set up Prisma configuration Create a new Prisma schema file: ```terminal npx prisma init --output ../generated/prisma ``` Update the `DATABASE_URL` in the `.env` file with your database connection string: ```env DATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE" ``` ## 3. Migrate the database schema ### 3.1. Introspect your database Run Prisma's introspection to create the Prisma schema from your existing database: ```terminal npx prisma db pull ``` This will create a `schema.prisma` file with your database schema. ### 3.2. Create a baseline migration Create and apply a baseline migration to mark the current state of your database: ```terminal npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > baseline.sql npx prisma migrate resolve --applied "baseline" ``` ## 4. Update your application code ### 4.1. Install Prisma Client Install the Prisma Client package: ```terminal npm install @prisma/client ``` Generate Prisma Client: ```terminal npx prisma generate ``` ### 4.2. Replace TypeORM queries Start replacing your TypeORM queries with Prisma Client. Here's an example of how to convert some common queries: <TabbedContent code> <TabItem value="TypeORM"> ```typescript // Find one const user = await userRepository.findOne({ where: { id: 1 } }); // Create const user = await userRepository.save({ email: 'alice@prisma.io', name: 'Alice' }); // Update await userRepository.update(1, { name: 'New name' }); // Delete await userRepository.delete(1); ``` </TabItem> <TabItem value="Prisma Client"> ```typescript // Find one const user = await prisma.user.findUnique({ where: { id: 1 } }); // Create const user = await prisma.user.create({ data: { email: 'alice@prisma.io', name: 'Alice' } }); // Update await prisma.user.update({ where: { id: 1 }, data: { name: 'New name' } }); // Delete await prisma.user.delete({ where: { id: 1 } }); ``` </TabItem> </TabbedContent> ### 4.3. Update your controllers Update your Express controllers to use Prisma Client. For example, here's how to update the `CreateUserAction`: ```typescript import { prisma } from '../client' export class CreateUserAction { async run(req: Request, res: Response) { const { email, name } = req.body const result = await prisma.user.create({ data: { email, name, }, }) return res.json(result) } } ``` ## 5. Test and deploy ### 5.1. Test your changes Test all migrated endpoints to ensure they work as expected: ```bash npm test ``` ### 5.2. Deploy your changes 1. Deploy your schema changes: ```bash npx prisma migrate deploy ``` 2. Deploy your application code with the updated dependencies. ## Next steps Now that you've migrated to Prisma ORM, you can: - Add more complex queries using Prisma's powerful query API - Set up Prisma Studio for database management - Implement database monitoring - Add automated tests using Prisma's testing utilities For more information: - [Prisma ORM documentation](/orm) - [Prisma Client API reference](/orm/prisma-client) --- # How to migrate from Sequelize to Prisma ORM URL: https://www.prisma.io/docs/guides/migrate-from-sequelize ## Introduction This guide shows you how to migrate your application from Sequelize to Prisma ORM. We'll use an extended version of the [Sequelize Express example](https://github.com/sequelize/express-example) as a [sample project](https://github.com/prisma/migrate-from-sequelize-to-prisma) to demonstrate the migration steps. This migration guide uses PostgreSQL as the example database, but it equally applies to any other relational database that's [supported by Prisma ORM](/orm/reference/supported-databases). You can learn how Prisma ORM compares to Sequelize on the [Prisma ORM vs Sequelize](/orm/more/comparisons/prisma-and-sequelize) page. ## Prerequisites Before starting this guide, make sure you have: - A Sequelize project you want to migrate - Node.js installed (version 18 or higher) - PostgreSQL or another supported database - Basic familiarity with Sequelize and Express.js ## 1. Prepare for migration ### 1.1. Understand the migration process The steps for migrating from Sequelize to Prisma ORM are always the same, no matter what kind of application or API layer you're building: 1. Install the Prisma CLI 2. Introspect your database 3. Create a baseline migration 4. Install Prisma Client 5. Gradually replace your Sequelize queries with Prisma Client These steps apply whether you're building a REST API (e.g., with Express, Koa, or NestJS), a GraphQL API (e.g., with Apollo Server, TypeGraphQL, or Nexus), or any other kind of application that uses Sequelize for database access. ### 1.2. Set up Prisma configuration Create a new Prisma schema file: ```terminal npx prisma init --output ../generated/prisma ``` This command created a new directory called `prisma` with the following files for you: - `schema.prisma`: Your Prisma schema that specifies your database connection and models - `.env`: A [`dotenv`](https://github.com/motdotla/dotenv) to configure your database connection URL as an environment variable The Prisma schema currently looks as follows: ```prisma file=prisma/schema.prisma showLineNumbers // This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } ``` :::tip If you're using VS Code, be sure to install the [Prisma VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) for syntax highlighting, formatting, auto-completion and a lot more cool features. ::: Update the `DATABASE_URL` in the `.env` file with your database connection string: ```env DATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE" ``` ## 2. Migrate the database schema ### 2.1. Introspect your database Run Prisma's introspection to create the Prisma schema from your existing database: ```terminal npx prisma db pull ``` This will create a `schema.prisma` file with your database schema. ### 2.2. Create a baseline migration To continue using Prisma Migrate to evolve your database schema, you will need to [baseline your database](/orm/prisma-migrate/getting-started). First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: ```terminal mkdir -p prisma/migrations/0_init ``` Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - `--from-empty`: assumes the data model you're migrating from is empty - `--to-schema-datamodel`: the current database state using the URL in the `datasource` block - `--script`: output a SQL script ```terminal wrap npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql npx prisma migrate resolve --applied 0_init ``` The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. ## 3. Update your application code ### 3.1. Install Prisma Client As a next step, you can install Prisma Client in your project so that you can start replacing the database queries in your project that are currently made with Sequelize: ```terminal npm install @prisma/client ``` After installing Prisma Client, you can generate the Prisma Client code: ```terminal npx prisma generate ``` ### 3.2. Replace Sequelize queries In this section, we'll show a few sample queries that are being migrated from Sequelize to Prisma Client based on the example routes from the sample REST API project. For a comprehensive overview of how the Prisma Client API differs from Sequelize, check out the [API comparison](/orm/more/comparisons/prisma-and-sequelize#api-comparison) page. <TabbedContent code> <TabItem value="Sequelize"> ```typescript // Find one const user = await User.findOne({ where: { id: 1 } }); // Create const user = await User.create({ email: 'alice@prisma.io', name: 'Alice' }); // Update await User.update({ name: 'New name' }, { where: { id: 1 } }); // Delete await User.destroy({ where: { id: 1 } }); ``` </TabItem> <TabItem value="Prisma Client"> ```typescript // Find one const user = await prisma.user.findUnique({ where: { id: 1 } }); // Create const user = await prisma.user.create({ data: { email: 'alice@prisma.io', name: 'Alice' } }); // Update await prisma.user.update({ where: { id: 1 }, data: { name: 'New name' } }); // Delete await prisma.user.delete({ where: { id: 1 } }); ``` </TabItem> </TabbedContent> ### 3.3. Update your controllers Update your Express controllers to use Prisma Client. For example, here's how to update a user controller: ```typescript import { prisma } from '../client' export class UserController { async create(req: Request, res: Response) { const { email, name } = req.body const result = await prisma.user.create({ data: { email, name, }, }) return res.json(result) } } ``` ## Next steps Now that you've migrated to Prisma ORM, you can: - Add more complex queries using Prisma's powerful query API - Set up Prisma Studio for database management - Implement database monitoring - Add automated tests using Prisma's testing utilities For more information: - [Prisma ORM documentation](/orm) - [Prisma Client API reference](/orm/prisma-client) --- # How to migrate from Mongoose to Prisma ORM URL: https://www.prisma.io/docs/guides/migrate-from-mongoose ## Introduction This guide shows you how to migrate your application from Mongoose to Prisma ORM. We'll use an extended version of the [Mongoose Express example](https://github.com/Automattic/mongoose/tree/master/examples/express) as a [sample project](https://github.com/prisma/migrate-from-mongoose-to-prisma) to demonstrate the migration steps. You can learn how Prisma ORM compares to Mongoose on the [Prisma ORM vs Mongoose](/orm/more/comparisons/prisma-and-mongoose) page. ## Prerequisites Before starting this guide, make sure you have: - A Mongoose project you want to migrate - Node.js installed (version 18 or higher) - MongoDB database - Basic familiarity with Mongoose and Express.js ## 1. Prepare for migration ### 1.1. Understand the migration process The steps for migrating from Mongoose to Prisma ORM are always the same, no matter what kind of application or API layer you're building: 1. Install the Prisma CLI 2. Introspect your database 3. Install and generate Prisma Client 4. Gradually replace your Mongoose queries with Prisma Client These steps apply whether you're building a REST API (e.g., with Express, Koa, or NestJS), a GraphQL API (e.g., with Apollo Server, TypeGraphQL, or Nexus), or any other kind of application that uses Mongoose for database access. ### 1.2. Set up Prisma configuration Create a new Prisma schema file: ```terminal npx prisma init --datasource-provider mongodb --output ../generated/prisma ``` This command creates: - A new directory called `prisma` that contains a `schema.prisma` file; your Prisma schema specifies your database connection and models - `.env`: A [`dotenv`](https://github.com/motdotla/dotenv) file at the root of your project (if it doesn't already exist), used to configure your database connection URL as an environment variable The Prisma schema currently looks as follows: ```prisma file=prisma/schema.prisma showLineNumbers // This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema datasource db { provider = "mongodb" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } ``` <br/> :::tip For an optimal development experience when working with Prisma ORM, refer to [editor setup](/orm/more/development-environment/editor-setup) to learn about syntax highlighting, formatting, auto-completion, and many more cool features. ::: Update the `DATABASE_URL` in the `.env` file with your MongoDB connection string: ```env DATABASE_URL="mongodb://USER:PASSWORD@HOST:PORT/DATABASE" ``` ## 2. Migrate the database schema ### 2.1. Introspect your database :::warning MongoDB is a _schemaless_ database. To incrementally adopt Prisma ORM in your project, ensure your database is populated with sample data. Prisma ORM introspects a MongoDB schema by sampling data stored and inferring the schema from the data in the database. ::: Run Prisma's introspection to create the Prisma schema from your existing database: ```terminal npx prisma db pull ``` This will create a `schema.prisma` file with your database schema. ```prisma file=prisma/schema.prisma showLineNumbers type UsersProfile { bio String } model categories { id String @id @default(auto()) @map("_id") @db.ObjectId v Int @map("__v") name String } model posts { id String @id @default(auto()) @map("_id") @db.ObjectId v Int @map("__v") author String @db.ObjectId categories String[] @db.ObjectId content String published Boolean title String } model users { id String @id @default(auto()) @map("_id") @db.ObjectId v Int @map("__v") email String @unique(map: "email_1") name String profile UsersProfile? } ``` ### 2.2. Update relations MongoDB doesn't support relations between different collections. However, you can create references between documents using the [`ObjectId`](/orm/overview/databases/mongodb#using-objectid) field type or from one document to many using an array of `ObjectIds` in the collection. The reference will store id(s) of the related document(s). You can use the `populate()` method that Mongoose provides to populate the reference with the data of the related document. Update the 1-n relationship between `posts` \<-> `users` as follows: - Rename the existing `author` reference in the `posts` model to `authorId` and add the `@map("author")` attribute - Add the `author` relation field in the `posts` model and it's `@relation` attribute specifying the `fields` and `references` - Add the `posts` relation in the `users` model Your schema should now look like this: ```prisma file=schema.prisma type UsersProfile { bio String } model categories { id String @id @default(auto()) @map("_id") @db.ObjectId v Int @map("__v") name String } model posts { id String @id @default(auto()) @map("_id") @db.ObjectId title String content String published Boolean v Int @map("__v") //delete-next-line author String @db.ObjectId //add-start author users @relation(fields: [authorId], references: [id]) authorId String @map("author") @db.ObjectId //add-end categories String[] @db.ObjectId } model users { id String @id @default(auto()) @map("_id") @db.ObjectId v Int @map("__v") email String @unique(map: "email_1") name String profile UsersProfile? //add-next-line posts posts[] } ``` Then, update the m-n between `posts` \<-\> `categories` references as follows: - Rename the `categories` field to `categoryIds` and map it using `@map("categories")` in the `posts` model - Add a new `categories` relation field in the `posts` model - Add the `postIds` scalar list field in the `categories` model - Add the `posts` relation in the `categories` model - Add a [relation scalar](/orm/prisma-schema/data-model/relations#annotated-relation-fields) on both models - Add the `@relation` attribute specifying the `fields` and `references` arguments on both sides Your schema should now look like this: ```prisma file=schema.prisma type UsersProfile { bio String } model categories { id String @id @default(auto()) @map("_id") @db.ObjectId v Int @map("__v") name String //add-start posts posts[] @relation(fields: [postIds], references: [id]) postIds String[] @db.ObjectId //add-end } model posts { id String @id @default(auto()) @map("_id") @db.ObjectId title String content String published Boolean v Int @map("__v") author users @relation(fields: [authorId], references: [id]) authorId String @map("author") @db.ObjectId //delete-next-line categories String[] @db.ObjectId //add-start categories categories[] @relation(fields: [categoryIds], references: [id]) categoryIds String[] @map("categories") @db.ObjectId //add-end } model users { id String @id @default(auto()) @map("_id") @db.ObjectId v Int @map("__v") email String @unique(map: "email_1") name String profile UsersProfile? posts posts[] } ``` ## 3. Update your application code ### 3.1. Install Prisma Client Install the Prisma Client package: ```terminal npm install @prisma/client ``` After installing the Prisma Client package, generate Prisma Client: ```terminal npx prisma generate ``` ### 3.2. Replace Mongoose queries Start replacing your Mongoose queries with Prisma Client. Here's an example of how to convert some common queries: <TabbedContent code> <TabItem value="Mongoose"> ```typescript // Find one const user = await User.findById(id); // Create const user = await User.create({ email: 'alice@prisma.io', name: 'Alice' }); // Update await User.findByIdAndUpdate(id, { name: 'New name' }); // Delete await User.findByIdAndDelete(id); ``` </TabItem> <TabItem value="Prisma Client"> ```typescript // Find one const user = await prisma.user.findUnique({ where: { id } }); // Create const user = await prisma.user.create({ data: { email: 'alice@prisma.io', name: 'Alice' } }); // Update await prisma.user.update({ where: { id }, data: { name: 'New name' } }); // Delete await prisma.user.delete({ where: { id } }); ``` </TabItem> </TabbedContent> ### 3.3. Update your controllers Update your Express controllers to use Prisma Client. For example, here's how to update a user controller: ```typescript import { prisma } from '../client' export class UserController { async create(req: Request, res: Response) { const { email, name } = req.body const result = await prisma.user.create({ data: { email, name, }, }) return res.json(result) } } ``` ## Next steps Now that you've migrated to Prisma ORM, you can: - Add more complex queries using Prisma's powerful query API - Set up Prisma Studio for database management - Implement database monitoring - Add automated tests using Prisma's testing utilities For more information: - [Prisma ORM documentation](/orm) - [Prisma Client API reference](/orm/prisma-client) --- # How to migrate from Drizzle to Prisma ORM URL: https://www.prisma.io/docs/guides/migrate-from-drizzle ## Introduction This guide shows you how to migrate your application from Drizzle to Prisma ORM. We'll use a sample project based off of the [Drizzle Next.js example](https://orm.drizzle.team/docs/tutorials/drizzle-nextjs-neon) to demonstrate the migration steps. You can find the example used for this guide on [GitHub](https://github.com/prisma/migrate-from-drizzle-to-prisma). You can learn how Prisma ORM compares to Drizzle on the [Prisma ORM vs Drizzle](/orm/more/comparisons/prisma-and-drizzle) page. ## Prerequisites Before starting this guide, make sure you have: - A Drizzle project you want to migrate - Node.js installed (version 16 or higher) - PostgreSQL or another supported database - Basic familiarity with Drizzle and Next.js :::note this migration guide uses Neon PostgreSQL as the example database, but it equally applies to any other relational database that are [supported by Prisma ORM](/orm/reference/supported-databases). ::: You can learn how Prisma ORM compares to Drizzle on the [Prisma ORM vs Drizzle](/orm/more/comparisons/prisma-and-drizzle) page. ## Overview of the migration process Note that the steps for migrating from Drizzle to Prisma ORM are always the same, no matter what kind of application or API layer you're building: 1. Install the Prisma CLI 1. Introspect your database 1. Create a baseline migration 1. Install Prisma Client 1. Gradually replace your Drizzle queries with Prisma Client These steps apply, no matter if you're building a REST API (e.g. with Express, koa or NestJS), a GraphQL API (e.g. with Apollo Server, TypeGraphQL or Nexus) or any other kind of application that uses Drizzle for database access. Prisma ORM lends itself really well for **incremental adoption**. This means, you don't have migrate your entire project from Drizzle to Prisma ORM at once, but rather you can _step-by-step_ move your database queries from Drizzle to Prisma ORM. ## Step 1. Install the Prisma CLI The first step to adopt Prisma ORM is to [install the Prisma CLI](/orm/tools/prisma-cli#installation) in your project: ```terminal copy npm install prisma --save-dev ``` ## Step 2. Introspect your database ### 2.1. Set up Prisma ORM Before you can introspect your database, you need to set up your [Prisma schema](/orm/prisma-schema) and connect Prisma to your database. Run the following command in the root of your project to create a basic Prisma schema file: ```terminal copy npx prisma init --output ../generated/prisma ``` This command created a new directory called `prisma` with the following files for you: - `schema.prisma`: Your Prisma schema that specifies your database connection and models - `.env`: A [`dotenv`](https://github.com/motdotla/dotenv) to configure your database connection URL as an environment variable :::note you may already have a `.env` file. If so, the `prisma init` command will append lines to it rather than creating a new file. ::: The Prisma schema currently looks as follows: ```prisma file=prisma/schema.prisma showLineNumbers // This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" } ``` :::tip If you're using VS Code, be sure to install the [Prisma VS Code extension](https://marketplace.visualstudio.com/items?itemName=Prisma.prisma) for syntax highlighting, formatting, auto-completion and a lot more cool features. ::: ### 2.2. Connect your database If you're not using PostgreSQL, you need to adjust the `provider` field on the `datasource` block to the database you currently use: <TabbedContent code> <TabItem value="PostgreSQL"> ```prisma file=schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } ``` </TabItem> <TabItem value="MySQL"> ```prisma file=schema.prisma showLineNumbers datasource db { provider = "mysql" url = env("DATABASE_URL") } ``` </TabItem> <TabItem value="Microsoft SQL Server"> ```prisma file=schema.prisma showLineNumbers datasource db { provider = "sqlserver" url = env("DATABASE_URL") } ``` </TabItem> <TabItem value="SQLite"> ```prisma file=schema.prisma showLineNumbers datasource db { provider = "sqlite" url = env("DATABASE_URL") } ``` </TabItem> </TabbedContent> Once that's done, you can configure your [database connection URL](/orm/reference/connection-urls) in the `.env` file. Drizzle and Prisma ORM use the same format for connection URLs, so your existing connection URL should work fine. ### 2.3. Introspect your database using Prisma ORM With your connection URL in place, you can [introspect](/orm/prisma-schema/introspection) your database to generate your Prisma models: ```terminal copy npx prisma db pull ``` If you're using the [sample project](https://github.com/prisma/migrate-from-drizzle-to-prisma) the following model would be created: ```prisma file=prisma/schema.prisma showLineNumbers model todo { id Int @id text String done Boolean @default(false) } ``` The generated Prisma model represents a database table. Prisma models are the foundation for your programmatic Prisma Client API which allows you to send queries to your database. ### 2.4. Create a baseline migration To continue using Prisma Migrate to evolve your database schema, you will need to [baseline your database](/orm/prisma-migrate/getting-started). First, create a `migrations` directory and add a directory inside with your preferred name for the migration. In this example, we will use `0_init` as the migration name: ```terminal mkdir -p prisma/migrations/0_init ``` Next, generate the migration file with `prisma migrate diff`. Use the following arguments: - `--from-empty`: assumes the data model you're migrating from is empty - `--to-schema-datamodel`: the current database state using the URL in the `datasource` block - `--script`: output a SQL script ```terminal wrap npx prisma migrate diff --from-empty --to-schema-datamodel prisma/schema.prisma --script > prisma/migrations/0_init/migration.sql ``` Review the generated migration to ensure everything is correct. Next, mark the migration as applied using `prisma migrate resolve` with the `--applied` argument. ```terminal npx prisma migrate resolve --applied 0_init ``` The command will mark `0_init` as applied by adding it to the `_prisma_migrations` table. You now have a baseline for your current database schema. To make further changes to your database schema, you can update your Prisma schema and use `prisma migrate dev` to apply the changes to your database. ### 2.5. Adjust the Prisma schema (optional) Models that are generated via introspection currently _exactly_ map to your database tables. In this section, you'll learn how you can adjust the naming of the Prisma models to adhere to [Prisma ORM's naming conventions](/orm/reference/prisma-schema-reference#naming-conventions). All of these adjustment are entirely optional and you are free to skip to the next step already if you don't want to adjust anything for now. You can go back and make the adjustments at any later point. As opposed to the current camelCase notation of Drizzle models, Prisma ORM's naming conventions are: - PascalCase for model names - camelCase for field names You can adjust the naming by _mapping_ the Prisma model and field names to the existing table and column names in the underlying database using `@@map` and `@map`. Here's an example on how you could modify the model above: ```prisma file=prisma/schema.prisma showLineNumbers model Todo { id Int @id text String done Boolean @default(false) @@map("todo") } ``` ## Step 3. Install and generate Prisma Client As a next step, you can install Prisma Client in your project so that you can start replacing the database queries in your project that are currently made with Drizzle: ```terminal npm install @prisma/client ``` After installing, you need to run `generate` in order to have your schema reflected in TypeScript types and autocomplete. ```terminal npx prisma generate ``` ## Step 4. Replace your Drizzle queries with Prisma Client In this section, we'll show a few sample queries that are being migrated from Drizzle to Prisma Client based on the example routes from the sample REST API project. For a comprehensive overview of how the Prisma Client API differs from Drizzle, check out the [comparison page](/orm/more/comparisons/prisma-and-drizzle#). First, to set up the `PrismaClient` instance that you'll use to send database queries from the various route handlers. Create a new file named `prisma.ts` in the `db` directory: ```terminal copy touch db/prisma.ts ``` Now, instantiate `PrismaClient` and export it from the file so you can use it in your route handlers later: ```ts copy file=db/prisma.ts showLineNumbers import { PrismaClient } from '@prisma/client' export const prisma = new PrismaClient() ``` ### 4.1. Replacing `getData` queries The fullstack Next.js app has several `actions` including `getData`. The `getData` action is currently implemented as follows: ```ts file=actions/todoActions.ts showLineNumbers import db from "@/db/drizzle"; import { todo } from "@/db/schema"; export const getData = async () => { const data = await db.select().from(todo); return data; }; ``` Here is the same action implemented using Prisma Client: ```ts file=src/controllers/FeedAction.ts showLineNumbers import { prisma } from "@/db/prisma"; export const getData = async () => { const data = await prisma.todo.findMany(); return data; }; ``` ### 4.2. Replacing queries in `POST` requests The [sample project](https://github.com/prisma/migrate-from-drizzle-to-prisma) has four actions that are utilized during `POST` requests: - `addTodo`: Creates a new `Todo` record - `deleteTodo`: Deletes an existing `Todo` record - `toggleTodo`: Toggles the boolean `done` field on an existing `Todo` record - `editTodo`: Edits the `text` field on an existing `Todo` record #### `addTodo` The `addTodo` action is currently implemented as follows: ```ts file=actions/todoActions.ts showLineNumbers import { revalidatePath } from "next/cache"; import db from "@/db/drizzle"; import { todo } from "@/db/schema"; export const addTodo = async (id: number, text: string) => { await db.insert(todo).values({ id: id, text: text, }); revalidatePath("/"); }; ``` Here is the same action implemented using Prisma Client: ```ts file=actions/todoActions.ts showLineNumbers import { revalidatePath } from "next/cache"; import { prisma } from "@/db/prisma"; export const addTodo = async (id: number, text: string) => { await prisma.todo.create({ data: { id, text }, }) revalidatePath("/"); }; ``` #### `deleteTodo` The `deleteTodo` action is currently implemented as follows: ```ts file=actions/todoActions.ts showLineNumbers import { eq } from "drizzle-orm"; import { revalidatePath } from "next/cache"; import db from "@/db/drizzle"; import { todo } from "@/db/schema"; export const deleteTodo = async (id: number) => { await db.delete(todo).where(eq(todo.id, id)); revalidatePath("/"); }; ``` Here is the same action implemented using Prisma Client: ```ts file=actions/todoActions.ts showLineNumbers import { revalidatePath } from "next/cache"; import { prisma } from "@/db/prisma"; export const deleteTodo = async (id: number) => { await prisma.todo.delete({ where: { id } }); revalidatePath("/"); }; ``` #### `toggleTodo` The `ToggleTodo` action is currently implemented as follows: ```ts file=actions/todoActions.ts showLineNumbers import { eq, not } from "drizzle-orm"; import { revalidatePath } from "next/cache"; import db from "@/db/drizzle"; import { todo } from "@/db/schema"; export const toggleTodo = async (id: number) => { await db .update(todo) .set({ done: not(todo.done), }) .where(eq(todo.id, id)); revalidatePath("/"); }; ``` Here is the same action implemented using Prisma Client: ```ts file=actions/todoActions.ts showLineNumbers import { revalidatePath } from "next/cache"; import { prisma } from "@/db/prisma"; export const toggleTodo = async (id: number) => { const todo = await prisma.todo.findUnique({ where: { id } }); if (todo) { await prisma.todo.update({ where: { id: todo.id }, data: { done: !todo.done }, }) revalidatePath("/"); } }; ``` Note that Prisma ORM does not have the ability to edit a boolean field "in place", so the record must be fetched before hand. #### `editTodo` The `editTodo` action is currently implemented as follows: ```ts file=actions/todoActions.ts showLineNumbers import { eq } from "drizzle-orm"; import { revalidatePath } from "next/cache"; import db from "@/db/drizzle"; import { todo } from "@/db/schema"; export const editTodo = async (id: number, text: string) => { await db .update(todo) .set({ text: text, }) .where(eq(todo.id, id)); revalidatePath("/"); }; ``` Here is the same action implemented using Prisma Client: ```ts file=actions/todoActions.ts showLineNumbers import { revalidatePath } from "next/cache"; import { prisma } from "@/db/prisma"; export const editTodo = async (id: number, text: string) => { await prisma.todo.update({ where: { id }, data: { text }, }) revalidatePath("/"); }; ``` ## More ### Implicit many-to-many relations Unlike Drizzle, Prisma ORM allows you to [model many-to-many relations _implicitly_](/orm/prisma-schema/data-model/relations/many-to-many-relations#implicit-many-to-many-relations). That is, a many-to-many relation where you do not have to manage the [relation table](/orm/prisma-schema/data-model/relations/many-to-many-relations#relation-tables) (also sometimes called JOIN table) _explicitly_ in your schema. Here is an example comparing Drizzle with Prisma ORM: ```ts file=schema.ts import { boolean, integer, pgTable, serial, text } from "drizzle-orm/pg-core"; export const posts = pgTable('post', { id: serial('serial').primaryKey(), title: text('title').notNull(), content: text('content'), published: boolean('published').default(false).notNull(), }); export const categories = pgTable('category', { id: serial('serial').primaryKey(), name: text('name').notNull(), }); export const postsToCategories = pgTable('posts_to_categories', { postId: integer('post_id').notNull().references(() => users.id), categoryId: integer('category_id').notNull().references(() => chatGroups.id), }); ``` This schema is equivalent to the following Prisma schema: ```prisma file=schema.prisma model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) postsToCategories PostToCategories[] @@map("post") } model Category { id Int @id @default(autoincrement()) name String postsToCategories PostToCategories[] @@map("category") } model PostToCategories { postId Int categoryId Int category Category @relation(fields: [categoryId], references: [id]) post Post @relation(fields: [postId], references: [id]) @@id([postId, categoryId]) @@index([postId]) @@index([categoryId]) @@map("posts_to_categories") } ``` In this Prisma schema, the many-to-many relation is modeled _explicitly_ via the relation table `PostToCategories`. By instead adhering to the conventions for Prisma ORM relation tables, the relation could look as follows: ```prisma file=schema.prisma showLineNumbers model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) categories Category[] } model Category { id Int @id @default(autoincrement()) name String posts Post[] } ``` This would also result in a more ergonomic and less verbose Prisma Client API to modify the records in this relation, because you have a direct path from `Post` to `Category` (and the other way around) instead of needing to traverse the `PostToCategories` model first. :::warning If your database provider requires tables to have primary keys then you have to use explicit syntax, and manually create the join model with a primary key. This is because relation tables (JOIN tables) created by Prisma ORM (expressed via `@relation`) for many-to-many relations using implicit syntax do not have primary keys. ::: --- # How to use Prisma ORM with Cloudflare D1 URL: https://www.prisma.io/docs/guides/cloudflare-d1 ## Introduction This guide shows you how to use Prisma ORM with Cloudflare D1, a serverless SQL database that runs on Cloudflare's edge network. You'll learn how to set up Prisma ORM with D1, handle migrations, and deploy your application to Cloudflare Workers. You can find a [deployment-ready example on GitHub](https://github.com/prisma/prisma-examples/blob/latest/deployment-platforms/edge/cloudflare-workers/with-d1). ## Prerequisites Before starting this guide, make sure you have: - A Cloudflare account - Node.js installed (version 18 or higher) - Wrangler CLI installed (version 3.39.0 or higher) - Basic familiarity with Cloudflare Workers and D1 ## 1. Configure Prisma schema In your Prisma schema, add the `driverAdapters` Preview feature to the `generator` block and set the `provider` of the `datasource` to `sqlite`. If you just bootstrapped the Prisma schema with `prisma init`, also be sure to add the following `User` model to it: ```prisma file=schema.prisma generator client { provider = "prisma-client-js" previewFeatures = ["driverAdapters"] } datasource db { provider = "sqlite" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) email String @unique name String? } ``` ## 2. Install dependencies Next, install the required packages: ```terminal npm install @prisma/adapter-d1 ``` Also, be sure to use a version of the Wrangler CLI that's above [`wrangler@^3.39.0`](https://github.com/cloudflare/workers-sdk/releases/tag/wrangler%403.39.0), otherwise the `--remote` flag that's used in the next sections won't be available. ## 3. Set up D1 database connection To connect your Workers with the D1 instance, add the following binding to your `wrangler.toml`: ```toml file=wrangler.toml name = "prisma-cloudflare-worker-example" main = "src/index.ts" compatibility_date = "2024-03-20" compatibility_flags = ["nodejs_compat"] [[d1_databases]] binding = "DB" # i.e. available in your Worker on env.DB database_name = "__YOUR_D1_DATABASE_NAME__" # to be replaced database_id = "__YOUR_D1_DATABASE_ID__" # to be replaced ``` Note that `__YOUR_D1_DATABASE_NAME__` and `__YOUR_D1_DATABASE_ID__` in the snippet above are placeholders that should be replaced with the database name and ID of your own D1 instance. If you weren't able to grab this ID from the terminal output, you can also find it in the Cloudflare Dashboard or by running `npx wrangler d1 list` and `npx wrangler d1 info __YOUR_D1_DATABASE_NAME__` in your terminal. ## 4. Set up database migrations :::note We recommend using `prisma migrate` in order to keep your data in D1 migrated. However, if you would prefer to use Cloudflare's migration system, [that workflow is also available](/orm/overview/databases/cloudflare-d1#using-the-wrangler-cli) ::: ### 4.1 Add needed environment variables In order to use the Prisma D1 adapter, you'll need to add a few secrets to a `.env` file: - `DATABASE_URL`: A path to your local D1 instance. Usually `"file:./prisma/db.sqlite"`. - `CLOUDFLARE_ACCOUNT_ID`: Your Cloudflare account ID, fetched via `npx wrangler whoami` - `CLOUDFLARE_DATABASE_ID`: The ID of your database, retrieved [during D1 database creation](#3-set-up-d1-database-connection). - `CLOUDFLARE_D1_TOKEN`: This API token is used by Prisma ORM to communicate with your D1 instance directly. To create this, follow these steps: 1. Visit https://dash.cloudflare.com/profile/api-tokens 2. Click "Create Token" 3. Click "Custom token" template 4. Fill out the template: Make sure you use a recognizable name and add the `Account / D1 / Edit` permission. 5. Click "Continue to summary" and then "Create Token". You can now store these secrets to be used by Prisma ORM. We recommend a `.env` file for local development, but any secret store will work. ```bash file=.env DATABASE_URL="file:./prisma/db.sqlite" CLOUDFLARE_ACCOUNT_ID="0773..." CLOUDFLARE_DATABASE_ID="01f30366-..." CLOUDFLARE_D1_TOKEN="F8Cg..." ``` ### 4.2 Configure Prisma Config Ensure that you have a `prisma.config.ts` file set up in the root of your project with a [migration driver adapter](/orm/reference/prisma-config-reference#migrateadapter) defined. ```ts import path from 'node:path' import type { PrismaConfig } from 'prisma' import { PrismaD1HTTP } from '@prisma/adapter-d1' // import your .env file import 'dotenv/config' type Env = { CLOUDFLARE_D1_TOKEN: string CLOUDFLARE_ACCOUNT_ID: string CLOUDFLARE_DATABASE_ID: string } export default { earlyAccess: true, schema: path.join('prisma', 'schema.prisma'), migration: { async adapter(env) { return new PrismaD1HTTP({ CLOUDFLARE_D1_TOKEN: env.CLOUDFLARE_D1_TOKEN, CLOUDFLARE_ACCOUNT_ID: env.CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_DATABASE_ID: env.CLOUDFLARE_DATABASE_ID, }) }, }, } satisfies PrismaConfig<Env> ``` This will allow `prisma migrate` to interact with your D1 database. ### 4.3 Run your first migration You can now run `prisma migrate dev` to migrate your database to match your local schema: ```terminal npx prisma migrate dev --name init ``` Let's also create some dummy data that we can query once the Worker is running. This time, we'll use wrangler to run a SQL statement without storing it in a file: ```terminal # For the local database npx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --command "INSERT INTO \"User\" (\"email\", \"name\") VALUES ('jane@prisma.io', 'Jane Doe (Local)');" --local # For the remote database npx wrangler d1 execute __YOUR_D1_DATABASE_NAME__ --command "INSERT INTO \"User\" (\"email\", \"name\") VALUES ('jane@prisma.io', 'Jane Doe (Remote)');" --remote ``` ## 5. Implement the Worker Before adding a Prisma Client query to your Worker, you need to generate Prisma Client with the following command: ``` npx prisma generate ``` In order to query your database from the Worker using Prisma ORM, you need to: 1. Add the `DB` binding to the `Env` interface. (Alternatively, you can run [`npx wrangler types`](https://developers.cloudflare.com/workers/wrangler/commands/#types) to generate the `Env` type from the binding in a separate file called `worker-configuration.d.ts`.) 2. Instantiate `PrismaClient` using the `PrismaD1` driver adapter. 3. Send a query using Prisma Client and return the result. Open `src/index.ts` and replace the entire content with the following: ```typescript file=src/index.ts import { PrismaClient } from '@prisma/client' import { PrismaD1 } from '@prisma/adapter-d1' export interface Env { DB: D1Database } export default { async fetch( request: Request, env: Env, ctx: ExecutionContext ): Promise<Response> { const adapter = new PrismaD1(env.DB) const prisma = new PrismaClient({ adapter }) const users = await prisma.user.findMany() const result = JSON.stringify(users) return new Response(result) }, } ``` ## 6. Run the Worker locally With the database query in place and Prisma Client generated, you can go ahead and run the Worker locally: ``` npm run dev ``` Now you can open your browser at [`http://localhost:8787`](http://localhost:8787/) to see the result of the database query: ```js no-copy ;[{ id: 1, email: 'jane@prisma.io', name: 'Jane Doe (Local)' }] ``` ## 7. Set the `DATABASE_URL` environment variable and deploy the Worker To deploy the Worker, run the the following command: ``` npm run deploy ``` Your deployed Worker is accessible via `https://prisma-d1-example.USERNAME.workers.dev`. If you navigate your browser to that URL, you should see the following data that's queried from your remote D1 database: ```js no-copy ;[{ id: 1, email: 'jane@prisma.io', name: 'Jane Doe (Remote)' }] ``` ## Next steps Now that you've set up Prisma ORM with Cloudflare D1, you can: - Add more complex queries using Prisma's powerful query API - Set up Prisma Studio for database management - Implement database monitoring - Add automated tests For more information: - [Prisma ORM documentation](/orm) - [Prisma Client API reference](/orm/prisma-client) - [Cloudflare D1 documentation](https://developers.cloudflare.com/d1) --- # How to use Prisma ORM with Turborepo URL: https://www.prisma.io/docs/guides/turborepo Prisma is a powerful ORM for managing databases, and [Turborepo](https://turbo.build/) simplifies monorepo workflows. By combining these tools, you can create a scalable, modular architecture for your projects. This guide will show you how to set up Prisma as a standalone package in a Turborepo monorepo, enabling efficient configuration, type sharing, and database management across multiple apps. ### What you'll learn: - How to set up Prisma in a Turborepo monorepo. - Steps to generate and reuse PrismaClient across packages. - Integrating the Prisma package into other applications in the monorepo. ## 1. Create your monorepo using turborepo To set up a Turborepo monorepo named `turborepo-prisma`, run the following command: ```terminal npx create-turbo@latest turborepo-prisma ``` After the setup, choose a package manager for the project. Navigate to the project root directory and install Turborepo as a development dependency: <TabbedContent code groupId="packageManager"> <TabItem value="npm"> ```terminal cd ./turborepo-prisma npm install turbo --save-dev ``` </TabItem> <TabItem value="yarn"> ```terminal cd ./turborepo-prisma yarn add turbo --dev --ignore-workspace-root-check ``` </TabItem> <TabItem value="pnpm"> ```terminal cd ./turborepo-prisma pnpm add turbo --save-dev --ignore-workspace-root-check ``` </TabItem> </TabbedContent> For more information about installing Turborepo, refer to the [official Turborepo guide](https://turbo.build/repo/docs/getting-started/installation). ## 2. Add a new `database` package to the `turborepo-prisma` monorepo Create a `database` package within the `packages` directory. Then, create a `package.json` file for the package by running: ```terminal cd packages/ mkdir database cd database touch package.json ``` Define the `package.json` file as follows: ```json file=packages/database/package.json showLineNumbers //add-start { "name": "@repo/db", "version": "0.0.0" } //add-end ``` Next, install the required dependencies to use Prisma ORM. Use your preferred package manager: <TabbedContent code groupId="packageManager"> <TabItem value="npm"> ```terminal npm install prisma --save-dev ``` </TabItem> <TabItem value="yarn"> ```terminal yarn add prisma --dev ``` </TabItem> <TabItem value="pnpm"> ```terminal pnpm add prisma --save-dev ``` </TabItem> </TabbedContent> ## 3. Initialize prisma by running `prisma init` Inside the `database` directory, initialize prisma by running: <TabbedContent code groupId="packageManager"> <TabItem value="npm"> ```terminal npx prisma init --db --output ../generated/prisma ``` </TabItem> <TabItem value="yarn"> ```terminal yarn prisma init --db --output ../generated/prisma ``` </TabItem> <TabItem value="pnpm"> ```terminal pnpm prisma init --db --output ../generated/prisma ``` </TabItem> </TabbedContent> This should create several files inside `packages/database`: - `prisma/schema.prisma` is where your [Prisma schema](/orm/prisma-schema/overview) lives. Here, you'll be able to modify the shape of your database. The `prisma init` command by default will create a configuration for `PostgreSQL` to be used. You can modify the schema to use any other [supported database](/orm/reference/supported-databases) by Prisma ORM. - `.gitignore` adds some ignored files to git - `.env` lets you manually specify your `DATABASE_URL` for prisma. Add a model to your Prisma schema in `packages/database/prisma/schema.prisma`: ```prisma file=packages/database/prisma/schema.prisma showLineNumbers datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" output = "../generated/prisma" } //add-start model User { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) email String @unique name String? } //add-end ``` :::warning It is recommended to add `../generated/prisma` to the `.gitignore` file because it contains platform-specific binaries that can cause compatibility issues across different environments. ::: ### The importance of generating Prisma types in a [custom directory](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path) In the `schema.prisma` file, we specify a custom `output` path where Prisma will generate its types. This ensures Prisma's types are resolved correctly across different package managers. > In this guide, the types will be generated in the `database/generated/prisma` directory. ## 4. Create scripts to execute Prisma CLI commands Let's add some scripts to the `package.json` inside `packages/database`: ```json file=packages/database/package.json showLineNumbers { "name": "@repo/db", "version": "0.0.0", //add-start "scripts": { "db:generate": "prisma generate", "db:migrate": "prisma migrate dev --skip-generate", "db:deploy": "prisma migrate deploy" }, //add-end "devDependencies": { "prisma": "^6.6.0" }, "dependencies": { "@prisma/client": "^6.6.0" } } ``` Let's also add these scripts to `turbo.json` in the root: ```json file=turbo.json showLineNumbers { "$schema": "https://turbo.build/schema.json", "ui": "tui", "tasks": { "build": { "dependsOn": ["^build"], "inputs": ["$TURBO_DEFAULT$", ".env*"], "outputs": [".next/**", "!.next/cache/**"] }, "lint": { "dependsOn": ["^lint"] }, "check-types": { "dependsOn": ["^check-types"] }, "dev": { "cache": false, "persistent": true }, //add-start "db:generate": { "cache": false }, "db:migrate": { "cache": false, "persistent": true // This is necessary to interact with the CLI and assign names to your database migrations. }, "db:deploy": { "cache": false } //add-end } ``` #### 1. Migrate your `prisma.schema` and generate types Navigate to the project root and run the following command to automatically migrate our database: <TabbedContent code> <TabItem value="npm"> ```terminal npx turbo db:migrate ``` </TabItem> <TabItem value="yarn"> ```terminal yarn turbo db:migrate ``` </TabItem> <TabItem value="pnpm"> ```terminal pnpm turbo db:migrate ``` </TabItem> </TabbedContent> #### 2. Generate your `prisma.schema` To generate the types from Prisma schema, from the project root run: <TabbedContent code> <TabItem value="npm"> ```terminal npx turbo db:generate ``` </TabItem> <TabItem value="yarn"> ```terminal yarn turbo db:generate ``` </TabItem> <TabItem value="pnpm"> ```terminal pnpm turbo db:generate ``` </TabItem> </TabbedContent> ## 5. Export prisma types and an instance of `PrismaClient` to be used across the monorepo Next, export the generated types and an instance of `PrismaClient` so it can used in your applications. In the `packages/database` directory, create a `src` folder and add a `client.ts` file. This file will define an instance of `PrismaClient`: ```ts file=packages/database/src/client.ts showLineNumbers //add-next-line import { PrismaClient } from "../generated/prisma"; //add-next-line const globalForPrisma = global as unknown as { prisma: PrismaClient }; //add-start export const prisma = globalForPrisma.prisma || new PrismaClient(); //add-end //add-next-line if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma; ``` Then create an `index.ts` file in the `src` folder to re-export the generated prisma types and the `PrismaClient` instance: ```ts file=packages/database/src/index.ts showLineNumbers //add-start export { prisma } from './client' // exports instance of prisma export * from "../generated/prisma" // exports generated types from prisma //add-end ``` Follow the [Just-in-Time packaging pattern](https://turbo.build/repo/docs/core-concepts/internal-packages#just-in-time-packages) and create an entrypoint to the package inside `packages/database/package.json`: ```json file=packages/database/package.json showLineNumbers { "name": "@repo/db", "version": "0.0.0", "scripts": { "db:generate": "npx prisma generate", "db:migrate": "npx prisma migrate dev --skip-generate", "db:deploy": "npx prisma migrate deploy" }, "devDependencies": { "prisma": "^6.6.0" }, "dependencies": { "@prisma/client": "^6.6.0" } //add-start "exports": { ".": "./src/index.ts" }, //add-end } ``` By completing these steps, you'll make the Prisma types and `PrismaClient` instance accessible throughout the monorepo. ## 6. Importing the `database` package into the `web` app in the monorepo The `turborepo-prisma` project should have an app called `web` at `apps/web`. Add the `database` dependency to `apps/web/package.json`: <TabbedContent code> <TabItem value="npm"> ```json { "dependencies": { //add-next-line "@repo/db": "*" } } ``` </TabItem> <TabItem value="yarn"> ```json { "dependencies": { //add-next-line "@repo/db": "*" } } ``` </TabItem> <TabItem value="pnpm"> ```json { "dependencies": { //add-next-line "@repo/db": "workspace:*" } } ``` </TabItem> </TabbedContent> Run your package manager's install command inside the `apps/web` directory: <TabbedContent code> <TabItem value="npm"> ```terminal cd apps/web npm install ``` </TabItem> <TabItem value="yarn"> ```terminal cd apps/web yarn install ``` </TabItem> <TabItem value="pnpm"> ```terminal cd apps/web pnpm install ``` </TabItem> </TabbedContent> Let's import the intantiated `prisma` client from the `database` package in the `web` app. In the `apps/web/app` directory, open the `page.tsx` file and add the following code: ```tsx file=apps/web/app/page.tsx showLineNumbers //add-start import styles from "./page.module.css"; import { prisma } from "@repo/db"; //add-end //add-start export default async function Home() { const user = await prisma.user.findFirst() return ( <div className={styles.page}> {user?.name ?? "No user added yet"} </div> ); } //add-end ``` Then, create a `.env` file in the `web` directory and copy into it the contents of the `.env` file from the `/database` directory containing the `DATABASE_URL`: ```env file=apps/web/.env //add-next-line DATABASE_URL="Same database url as used in the database directory" ``` :::note If you want to use a single `.env` file in the root directory across your apps and packages in a Turborepo setup, consider using a package like [`dotenvx`](https://dotenvx.com/docs/monorepos/turborepo). To implement this, update the `package.json` files for each package or app to ensure they load the required environment variables from the shared `.env` file. For detailed instructions, refer to the [`dotenvx` guide for Turborepo](https://dotenvx.com/docs/monorepos/turborepo). Keep in mind that Turborepo [recommends using separate `.env` files for each package](https://turbo.build/repo/docs/crafting-your-repository/using-environment-variables#use-env-files-in-packages) to promote modularity and avoid potential conflicts. ::: ## 7. Setup dependent tasks The `db:generate` and `db:deploy` scripts are not yet optimized for the monorepo setup but are essential for the `dev` and `build` tasks. If a new developer runs `turbo dev` on an application without first running `db:generate`, they will encounter errors. To prevent this, ensure that `db:generate` is always executed before running `dev` or `build`. Additionally, make sure both `db:deploy` and `db:generate` are executed before `db:build`. Here's how to configure this in your `turbo.json` file: ```json file=turbo.json showLineNumbers { "$schema": "https://turbo.build/schema.json", "ui": "tui", "tasks": { "build": { //add-next-line "dependsOn": ["^build", "^db:generate"], "inputs": ["$TURBO_DEFAULT$", ".env*"], "outputs": [".next/**", "!.next/cache/**"] }, "lint": { "dependsOn": ["^lint"] }, "check-types": { "dependsOn": ["^check-types"] }, "dev": { //add-next-line "dependsOn": ["^db:generate"], "cache": false, "persistent": true }, "db:generate": { "cache": false }, "db:migrate": { "cache": false, "persistent": true }, "db:deploy": { "cache": false } } } ``` ## 8. Run the project in development :::warning Before starting the development server, note that if you are using Next.js v15.2.0, do not use Turbopack as there is a known [issue](https://github.com/vercel/next.js/issues/76497). Remove Turbopack from your dev script by updating your `apps/web/package.json` ```json file=apps/web/package.json "script":{ //delete-next-line "dev": "next dev --turbopack --port 3000", //add-next-line "dev": "next dev --port 3000", } ``` ::: Then from the project root run the project: <TabbedContent code> <TabItem value="npm"> ```terminal npx turbo run dev --filter=web ``` </TabItem> <TabItem value="yarn"> ```terminal yarn turbo run dev --filter=web ``` </TabItem> <TabItem value="pnpm"> ```terminal pnpm turbo run dev --filter=web ``` </TabItem> </TabbedContent> Navigate to the `http://localhost:3000` and you should see the message: ``` No user added yet ``` :::note You can add users to your database by creating a seed script or manually by using [Prisma Studio](/orm/tools/prisma-studio). To use Prisma Studio to add manually data via a GUI, navigate inside the `packages/database` directory and run `prisma studio` using your package manager: <TabbedContent code> <TabItem value="npm"> ```terminal npx prisma studio ``` </TabItem> <TabItem value="yarn"> ```terminal yarn prisma studio ``` </TabItem> <TabItem value="pnpm"> ```terminal pnpm prisma studio ``` </TabItem> </TabbedContent> This command starts a server with a GUI at http://localhost:5555, allowing you to view and modify your data. ::: Congratulations, you're done setting up Prisma for Turborepo! ## Next Steps - Expand your Prisma models to handle more complex data relationships. - Implement additional CRUD operations to enhance your application's functionality. - Check out [Prisma Postgres](https://www.prisma.io/postgres) to see how you can scale your application. ### More Info - [Turborepo Docs](https://turbo.build/repo/docs) - [Next.js Docs](https://nextjs.org/docs) - [Prisma ORM Docs](/orm/overview/introduction) --- # How to use Prisma ORM with Next.js URL: https://www.prisma.io/docs/guides/nextjs ## Introduction This guide shows you how to use Prisma ORM with Next.js 15, a fullstack React framework. You'll learn how to set up Prisma ORM with Next.js, handle migrations, and deploy your application to Vercel. You can find a [deployment-ready example on GitHub](https://github.com/prisma/prisma-examples/blob/latest/orm/nextjs). ## Prerequisites Before starting this guide, make sure you have: - Node.js 18+ installed - A [Prisma Postgres](https://www.prisma.io/postgres) database (or any PostgreSQL database) - A Vercel account (if you want to deploy your application) ## 1. Set up your project From the directory where you want to create your project, run `create-next-app` to create a new Next.js app that we will be using for this guide. ```terminal npx create-next-app@latest my-app ``` You will be prompted to answer a few questions about your project. Select all of the defaults. :::info For completeness, those are: - TypeScript - ESLint - Tailwind CSS - No `src` directory - App Router - Turbopack - No customized import alias ::: Then, navigate to the project directory: ```terminal cd my-app ``` ## 2. Set up Prisma ORM ### 2.1 Install Prisma ORM and create your first models First, we need to install a few dependencies. At the root of your project in your terminal, run: ```terminal npm install prisma --save-dev npm install tsx --save-dev npm install @prisma/extension-accelerate ``` :::info If you're not using a Prisma Postgres database, you won't need the `@prisma/extension-accelerate` package. ::: Then, run `prisma init` to initialize Prisma ORM in your project. ```terminal npx prisma init --output ../src/app/generated/prisma ``` This will create a new `prisma` directory in your project, with a `schema.prisma` file inside of it. The `schema.prisma` file is where you will define your database models. The `prisma init` command also creates a `.env` file in your project root to store your database connection string and outputs the generated client into `/app/generated/prisma`. Next, let's add two models to your `schema.prisma` file. A `User` model and a `Post` model. ```prisma file=prisma/schema.prisma generator client { provider = "prisma-client-js" output = "../src/app/generated/prisma" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } //add-start model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) authorId Int author User @relation(fields: [authorId], references: [id]) } //add-end ``` This represents a simple blog with users and posts. Each `Post` can have a `User` as an author and each `User` can have many `Post`s. Now that we have a Prisma Schema and a model, let's connect to our Prisma Postgres database. ### 2.2 Save your database connection string Now that you have your Prisma schema, you will need a database to apply your schema to. :::note[I don't have a database yet] If you don't have a database yet, you can create a new one through the [Prisma Console](https://console.prisma.io/). Step-by-step instructions are available in our [getting started guide](/getting-started/quickstart-prismaPostgres#1-set-up-a-prisma-postgres-database-in-the-platform-console). ::: When you have created your Prisma Postgres project, you'll get a `DATABASE_URL`. Store it in your `.env` file. ```env file=.env DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIU..."" ``` ### 2.3 Update your database schema :::warning If you're connecting to a database with existing data, use the `prisma db pull` command and then skip to [Set up Prisma Client](#25-set-up-prisma-client). ::: Now that you've saved your database connection string, we can apply your schema to your database using the `prisma migrate dev` command. ```terminal npx prisma migrate dev --name init ``` This creates an initial migration creating the `User` and `Post` tables and applies that migration to your database. Now, let's add some initial data to our database. ### 2.4 Seed your database Prisma ORM has built-in support for seeding your database with initial data. To do this, you can create a new file called `seed.ts` in the `prisma` directory. ```ts file=prisma/seed.ts import { PrismaClient, Prisma } from '../src/app/generated/prisma' const prisma = new PrismaClient() const userData: Prisma.UserCreateInput[] = [ { name: 'Alice', email: 'alice@prisma.io', posts: { create: [ { title: 'Join the Prisma Discord', content: 'https://pris.ly/discord', published: true, }, { title: 'Prisma on YouTube', content: 'https://pris.ly/youtube', }, ], }, }, { name: 'Bob', email: 'bob@prisma.io', posts: { create: [ { title: 'Follow Prisma on Twitter', content: 'https://www.twitter.com/prisma', published: true, }, ], }, } ] export async function main() { for (const u of userData) { await prisma.user.create({ data: u }) } } main() ``` Now, add the `prisma.seed` configuration to your `package.json` file. ```json file=package.json { "name": "my-app", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev --turbopack", "build": "next build", "start": "next start", "lint": "next lint" }, //add-start "prisma": { "seed": "tsx prisma/seed.ts" }, //add-end "dependencies": { "@prisma/client": "^6.2.1", "@prisma/extension-accelerate": "^1.2.1", "next": "15.1.4", "react": "^19.0.0", "react-dom": "^19.0.0" }, "devDependencies": { "@eslint/eslintrc": "^3", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", "eslint-config-next": "15.1.4", "postcss": "^8", "prisma": "^6.2.1", "tailwindcss": "^3.4.1", "tsx": "^4.19.2", "typescript": "^5" } } ``` :::warning Before starting the development server, note that if you are using Next.js v15.2.0, do not use Turbopack as there is a known [issue](https://github.com/vercel/next.js/issues/76497). Remove Turbopack from your dev script by updating your `package.json` ```json file=package.json "script":{ //delete-start "dev": "next dev --turbopack", //delete-end //add-start "dev": "next dev", //add-end } ``` ::: Finally, run `prisma db seed` to seed your database with the initial data we defined in the `seed.ts` file. ```terminal npx prisma db seed ``` We now have a database with some initial data! You can check out the data in your database by running `prisma studio`. ```terminal npx prisma studio ``` ### 2.5 Set up Prisma Client Now that we have a database with some initial data, we can set up Prisma Client and connect it to our database. At the root of your project, create a new `lib` directory and add a `prisma.ts` file to it. ```terminal mkdir -p src/lib && touch src/lib/prisma.ts ``` Now, add the following code to your `lib/prisma.ts` file: ```ts file=lib/prisma.ts import { PrismaClient } from '../src/app/generated/prisma' import { withAccelerate } from '@prisma/extension-accelerate' const globalForPrisma = global as unknown as { prisma: PrismaClient } const prisma = globalForPrisma.prisma || new PrismaClient().$extends(withAccelerate()) if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma export default prisma ``` This file creates a Prisma Client and attaches it to the global object so that only one instance of the client is created in your application. This helps resolve issues with hot reloading that can occur when using Prisma ORM with Next.js in development mode. :::note If you're not using Prisma Postgres, replace the line ```ts const prisma = globalForPrisma.prisma || new PrismaClient().$extends(withAccelerate()) ``` with ```ts const prisma = globalForPrisma.prisma || new PrismaClient() ``` and remove the `@prisma/extension-accelerate` import. ::: We'll use this client in the next section to run your first queries. ## 3. Query your database with Prisma ORM Now that we have an initialized Prisma Client, a connection to our database, and some initial data, we can start querying our data with Prisma ORM. In our example, we'll be making the "home" page of our application display all of our users. Open the `app/page.tsx` file and replace the existing code with the following: ```tsx file=app/page.tsx export default async function Home() { return ( <div className="min-h-screen bg-gray-50 flex flex-col items-center justify-center -mt-16"> <h1 className="text-4xl font-bold mb-8 font-[family-name:var(--font-geist-sans)] text-[#333333]"> Superblog </h1> <ol className="list-decimal list-inside font-[family-name:var(--font-geist-sans)]"> <li className="mb-2">Alice</li> <li>Bob</li> </ol> </div> ); } ``` This gives us a basic page with a title and a list of users. However, that list is static and doesn't change. Let's update the page to fetch the users from our database and make it dynamic. ```tsx file=app/page.tsx //add-start import prisma from '@/lib/prisma' //add-end export default async function Home() { //add-start const users = await prisma.user.findMany(); //add-end return ( <div className="min-h-screen bg-gray-50 flex flex-col items-center justify-center -mt-16"> <h1 className="text-4xl font-bold mb-8 font-[family-name:var(--font-geist-sans)] text-[#333333]"> Superblog </h1> <ol className="list-decimal list-inside font-[family-name:var(--font-geist-sans)]"> //add-start {users.map((user) => ( <li key={user.id} className="mb-2"> {user.name} </li> ))} //add-end </ol> </div> ); } ``` We are now importing our client, querying the `User` model for all users, and then displaying them in a list. Now your home page is dynamic and will display the users from your database. ### 3.1 Update your data (optional) If you want to see what happens when data is updated, you could: - update your `User` table via a SQL browser of your choice - change your `seed.ts` file to add more users - change the call to `prisma.user.findMany` to re-order the users, filter the users, or similar. Just reload the page and you'll see the changes. ## 4. Add a new Posts list page We have our home page working, but we should add a new page that displays all of our posts. First create a new `posts` directory in the `app` directory and create a new `page.tsx` file inside of it. ```terminal mkdir -p src/app/posts && touch src/app/posts/page.tsx ``` Second, add the following code to the `app/posts/page.tsx` file: ```tsx file=app/posts/page.tsx import prisma from "@/lib/prisma"; export default async function Posts() { return ( <div className="min-h-screen bg-gray-50 flex flex-col items-center justify-center -mt-16"> <h1 className="text-4xl font-bold mb-8 font-[family-name:var(--font-geist-sans)] text-[#333333]"> Posts </h1> <ul className="font-[family-name:var(--font-geist-sans)] max-w-2xl space-y-4"> <li>My first post</li> </ul> </div> ); } ``` Now `localhost:3000/posts` will load, but the content is static. Let's update it to be dynamic, similarly to the home page: ```tsx file=app/posts/page.tsx import prisma from "@/lib/prisma"; export default async function Posts() { //add-start const posts = await prisma.post.findMany({ include: { author: true, }, }); //add-end return ( <div className="min-h-screen bg-gray-50 flex flex-col items-center justify-center -mt-16"> <h1 className="text-4xl font-bold mb-8 font-[family-name:var(--font-geist-sans)] text-[#333333]"> Posts </h1> <ul className="font-[family-name:var(--font-geist-sans)] max-w-2xl space-y-4"> //delete-start <li>My first post</li> //delete-end //add-start {posts.map((post) => ( <li key={post.id}> <span className="font-semibold">{post.title}</span> <span className="text-sm text-gray-600 ml-2"> by {post.author.name} </span> </li> ))} //add-end </ul> </div> ); } ``` This works similarly to the home page, but instead of displaying users, it displays posts. You can also see that we've used `include` in our Prisma Client query to fetch the author of each post so we can display the author's name. This "list view" is one of the most common patterns in web applications. We're going to add two more pages to our application which you'll also commonly need: a "detail view" and a "create view". ## 5. Add a new Posts detail page To complement the Posts list page, we'll add a Posts detail page. In the `posts` directory, create a new `[id]` directory and a new `page.tsx` file inside of that. ```terminal mkdir -p src/app/posts/[id] && touch src/app/posts/[id]/page.tsx ``` This page will display a single post's title, content, and author. Just like our other pages, add the following code to the `app/posts/new/page.tsx` file: ```tsx file=app/posts/[id]/page.tsx import prisma from "@/lib/prisma"; export default async function Post({ params }: { params: Promise<{ id: string }> }) { return ( <div className="min-h-screen bg-gray-50 flex flex-col items-center justify-center -mt-16"> <article className="max-w-2xl space-y-4 font-[family-name:var(--font-geist-sans)]"> <h1 className="text-4xl font-bold mb-8 text-[#333333]">My first post</h1> <p className="text-gray-600 text-center">by Anonymous</p> <div className="prose prose-gray mt-8"> No content available. </div> </article> </div> ); } ``` As before, this page is static. Let's update it to be dynamic based on the `params` passed to the page: ```tsx file=app/posts/[id]/page.tsx import prisma from "@/lib/prisma"; //add-start import { notFound } from "next/navigation"; //add-end export default async function Post({ params }: { params: Promise<{ id: string }> }) { //add-start const { id } = await params; const post = await prisma.post.findUnique({ where: { id: parseInt(id) }, include: { author: true, }, }); if (!post) { notFound(); } //add-end return ( <div className="min-h-screen bg-gray-50 flex flex-col items-center justify-center -mt-16"> <article className="max-w-2xl space-y-4 font-[family-name:var(--font-geist-sans)]"> //delete-start <h1 className="text-4xl font-bold mb-8 text-[#333333]">My first post</h1> <p className="text-gray-600 text-center">by Anonymous</p> <div className="prose prose-gray mt-8"> No content available. </div> //delete-end //add-start <h1 className="text-4xl font-bold mb-8 text-[#333333]">{post.title}</h1> <p className="text-gray-600 text-center">by {post.author.name}</p> <div className="prose prose-gray mt-8"> {post.content || "No content available."} </div> //add-end </article> </div> ); } ``` There's a lot of changes here, so let's break it down: - We're using Prisma Client to fetch the post by its `id`, which we get from the `params` object. - In case the post doesn't exist (maybe it was deleted or maybe you typed a wrong ID), we call `notFound()` to display a 404 page. - We then display the post's title, content, and author. If the post doesn't have content, we display a placeholder message. It's not the prettiest page, but it's a good start. Try it out by navigating to `localhost:3000/posts/1` and `localhost:3000/posts/2`. You can also test the 404 page by navigating to `localhost:3000/posts/999`. ## 6. Add a new Posts create page To round out our application, we'll add a "create" page for posts. This will let you write your own posts and save them to the database. As with the other pages, we'll start with a static page and then update it to be dynamic. ```terminal mkdir -p src/app/posts/new && touch src/app/posts/new/page.tsx ``` Now, add the following code to the `app/posts/new/page.tsx` file: ```tsx file=app/posts/new/page.tsx import Form from "next/form"; export default function NewPost() { async function createPost(formData: FormData) { "use server"; const title = formData.get("title") as string; const content = formData.get("content") as string; } return ( <div className="max-w-2xl mx-auto p-4"> <h1 className="text-2xl font-bold mb-6">Create New Post</h1> <Form action={createPost} className="space-y-6"> <div> <label htmlFor="title" className="block text-lg mb-2"> Title </label> <input type="text" id="title" name="title" placeholder="Enter your post title" className="w-full px-4 py-2 border rounded-lg" /> </div> <div> <label htmlFor="content" className="block text-lg mb-2"> Content </label> <textarea id="content" name="content" placeholder="Write your post content here..." rows={6} className="w-full px-4 py-2 border rounded-lg" /> </div> <button type="submit" className="w-full bg-blue-500 text-white py-3 rounded-lg hover:bg-blue-600" > Create Post </button> </Form> </div> ); } ``` This form looks good, but it doesn't do anything yet. Let's update the `createPost` function to save the post to the database: ```tsx file=app/posts/new/page.tsx import Form from "next/form"; //add-start import prisma from "@/lib/prisma"; import { revalidatePath } from "next/cache"; import { redirect } from "next/navigation"; //add-end export default function NewPost() { async function createPost(formData: FormData) { "use server"; const title = formData.get("title") as string; const content = formData.get("content") as string; //add-start await prisma.post.create({ data: { title, content, authorId: 1, }, }); revalidatePath("/posts"); redirect("/posts"); //add-end } return ( <div className="max-w-2xl mx-auto p-4"> <h1 className="text-2xl font-bold mb-6">Create New Post</h1> <Form action={createPost} className="space-y-6"> <div> <label htmlFor="title" className="block text-lg mb-2"> Title </label> <input type="text" id="title" name="title" placeholder="Enter your post title" className="w-full px-4 py-2 border rounded-lg" /> </div> <div> <label htmlFor="content" className="block text-lg mb-2"> Content </label> <textarea id="content" name="content" placeholder="Write your post content here..." rows={6} className="w-full px-4 py-2 border rounded-lg" /> </div> <button type="submit" className="w-full bg-blue-500 text-white py-3 rounded-lg hover:bg-blue-600" > Create Post </button> </Form> </div> ); } ``` This page now has a functional form! When you submit the form, it will create a new post in the database and redirect you to the posts list page. We also added a `revalidatePath` call to revalidate the posts list page so that it will be updated with the new post. That way everyone can read the new post immediately. Try it out by navigating to `localhost:3000/posts/new` and submitting the form. ## 7. Deploy your application to Vercel (Optional) The quickest way to deploy your application to Vercel is to use the [Vercel CLI](https://vercel.com/docs/cli). First, install the Vercel CLI: ```terminal npm install -g vercel ``` Then, run `vercel login` to log in to your Vercel account. ```terminal vercel login ``` Before we deploy, we also need to tell Vercel to make sure that the Prisma Client is generated. You can do this by adding a `postinstall` script to your `package.json` file. ```json file=package.json { "name": "my-app", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev --turbopack", "build": "next build", //add-next-line "postinstall": "prisma generate", "start": "next start", "lint": "next lint" }, "prisma": { "seed": "tsx prisma/seed.ts" }, "dependencies": { "@prisma/client": "^6.2.1", "@prisma/extension-accelerate": "^1.2.1", "next": "15.1.4", "react": "^19.0.0", "react-dom": "^19.0.0" }, "devDependencies": { "@eslint/eslintrc": "^3", "@types/node": "^20", "@types/react": "^19", "@types/react-dom": "^19", "eslint": "^9", "eslint-config-next": "15.1.4", "postcss": "^8", "prisma": "^6.2.1", "tailwindcss": "^3.4.1", "tsx": "^4.19.2", "typescript": "^5" } } ``` After this change, you can deploy your application to Vercel by running `vercel`. ```terminal vercel ``` After the deployment is complete, you can visit your application at the URL that Vercel provides. Congratulations, you've just deployed a Next.js application with Prisma ORM! ## 8. Next steps Now that you have a working Next.js application with Prisma ORM, here are some ways you can expand and improve your application: - Add authentication to protect your routes - Add the ability to edit and delete posts - Add comments to posts - Use [Prisma Studio](/orm/tools/prisma-studio) for visual database management For more information: - [Prisma ORM documentation](/orm) - [Prisma Client API reference](/orm/prisma-client) - [Next.js documentation](https://nextjs.org/docs) --- # How to use Prisma ORM with Nuxt URL: https://www.prisma.io/docs/guides/nuxt The [Prisma Nuxt module](/orm/more/help-and-troubleshooting/prisma-nuxt-module) helps you get started with Prisma in [Nuxt](https://nuxt.com/) applications by simplifying the initial setup process. This guide explains how to set up a Nuxt application, configure [Prisma Postgres](https://prisma.io/postgres) using the Prisma Nuxt module, and deploy the project to [Vercel](https://vercel.com/) for production. Here's what you'll learn: - How to set up a Nuxt project with the Prisma Nuxt module. - How to configure and use Prisma Postgres with the Prisma Nuxt module in your Nuxt app. - How to deploy the project to Vercel. ## Prerequisites To follow this guide, ensure you have the following: - Node.js version: A [compatible Node.js version](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6#minimum-supported-nodejs-versions) required for Prisma 6. - Accounts: - [GitHub](https://github.com) - [Prisma Data Platform](https://console.prisma.io) - [Vercel](https://vercel.com) - Basic knowledge of Git and Vercel deployment (helpful but not required). ## 1. Create a New Nuxt Project and set up the Prisma Nuxt module 1. Initialize [a new Nuxt project](https://nuxt.com/docs/getting-started/installation#new-project), select `npm` as the package manager and initialize git: ```terminal npm create nuxt hello-world ``` :::note We recommend using `npm` as it is the most stable option with the `@prisma/nuxt` module. ::: 2. Navigate into the project directory and install the `@prisma/nuxt` module: ```terminal cd hello-world npm i @prisma/nuxt ``` 3. Install the [Prisma Accelerate client extension](https://www.npmjs.com/package/@prisma/extension-accelerate) as it's required to use Prisma Postgres: ```terminal npm i @prisma/extension-accelerate ``` 4. Add the `@prisma/nuxt` module with the following configuration to your `nuxt.config.ts` file: ```typescript // https://nuxt.com/docs/api/configuration/nuxt-config export default defineNuxtConfig({ compatibilityDate: "2024-11-01", modules: ["@prisma/nuxt"], experimental: { componentIslands: true, }, devtools: { enabled: true }, }); ``` ## 2. Setup Prisma ORM by running the development server locally After configuring your Nuxt project with the Prisma module, the next step is to set up Prisma ORM. This process begins by starting the development server, which automatically configures Prisma with a [SQLite database](/orm/overview/databases/sqlite). Run the following command to start the development server: ```terminal npm run dev ``` After running this command, you will be prompted to run a database migration with [Prisma Migrate](/orm/prisma-migrate/understanding-prisma-migrate/overview): ```terminal ? Do you want to migrate database changes to your database? › (Y/n) ``` Confirm that you want to migrate your database and create your initial tables by hitting <kbd>Y</kbd> on your keyboard. Once the setup flow has terminated, it: 1. Installed the [Prisma CLI](/orm/reference/prisma-cli-reference). 2. Initialized a Prisma project with a SQLite database. 3. Created sample `User` and `Post` models in the `schema.prisma` file: ```prisma file=prisma/schema.prisma // This is your Prisma schema file, // learn more about it in the docs: https://pris.ly/d/prisma-schema generator client { provider = "prisma-client-js" } datasource db { provider = "sqlite" url = env("DATABASE_URL") } model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) author User @relation(fields: [authorId], references: [id]) authorId Int } ``` 4. Created the database tables for the `User` and `Post` models from the previous steps. :::note The database migrates automatically the first time you start the module if there isn't a `migrations` folder. After that, you need to run `npx prisma migrate dev` manually in the CLI to apply any schema changes. Running the `npx prisma migrate dev` command manually makes it easier and safer to manage migrations and also to [troubleshoot](/orm/prisma-migrate/workflows/troubleshooting) any migration-related errors. ::: 5. Installed and generated [Prisma Client](https://da-2255.docs-51g.pages.dev/orm/reference/prisma-client-reference) which enables you to query your DB. 6. Installed [Prisma Studio](/orm/tools/prisma-studio). When the Prisma setup is complete, the development server should start on `https://localhost:3000`. Next, stop the server, as we need to make some code changes. ## 4. Update the application code With Prisma configured, the next step is to update your application code to fetch and display data from your database. 1. In the root directory of your project, create a folder named `components`. 2. Inside the `components` folder, create a file named `User.server.vue`. This server component will fetch and display the name of the first user from the database: ```html file=components/User.server.vue <script setup> import { withAccelerate } from "@prisma/extension-accelerate"; const prisma = usePrismaClient().$extends(withAccelerate()); const user = await prisma.user.findFirst(); </script> <template> <p>{{ user?.name ?? "No user has been added yet." }}</p> </template> ``` :::note We're extending the `usePrismaClient()` composable with the `withAccelerate()` extension method to ensure [compatibility with Prisma Postgres](/postgres/overview#using-the-client-extension-for-prisma-accelerate-required). This extension will also allow you to [cache your queries](/accelerate/caching). ::: 3. Modify the `app.vue` file in the root directory to include the new server component using Nuxt Islands: ```html file=app.vue <template> <div> <NuxtIsland name="User"></NuxtIsland> </div> </template> ``` 4. Run the following command to start the development server again: ```terminal npm run dev ``` 5. Verify the application code is working by opening your application in a browser at `https://localhost:3000`. As there are no users in the database yet, the application will display: ```no-copy No user has been added yet. ``` This message will dynamically update when users are added to your database. By completing these steps, your application is now capable of fetching data from your Prisma database and rendering it on the frontend. ## 5. Create a Prisma Postgres instance To store your app's data, you'll create a Prisma Postgres database instance using the Prisma Data Platform. Follow these steps to create your Prisma Postgres database: 1. Log in to [Prisma Data Platform](https://console.prisma.io/) and open the Console. 1. In a [workspace](/platform/about#workspace) of your choice, click the **New project** button. 1. Type a name for your project in the **Name** field, e.g. **hello-ppg**. 1. In the **Prisma Postgres** section, click the **Get started** button. 1. In the **Region** dropdown, select the region that's closest to your current location, e.g. **US East (N. Virginia)**. 1. Click the **Create project** button. At this point, you'll be redirected to the **Database** page where you will need to wait for a few seconds while the status of your database changes from **`PROVISIONING`** to **`CONNECTED`**. Once the green **`CONNECTED`** label appears, your database is ready to use! Then, find your database credentials in the **Set up database access** section, copy the `DATABASE_URL` environment variable`. ```bash no-copy DATABASE_URL=<your-database-url> ``` The `DATABASE_URL` environment variable will be required in the next steps. ## 6. Set up Prisma Postgres in your Nuxt app Now that the Prisma Postgres instance is ready, update your Nuxt application to use this database: 1. Update the `.env` file by replacing the existing `DATABASE_URL` value with the one you previously copied. It will look similar to this: ```terminal file=.env // edit-next-line DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=PRISMA_POSTGRES_API_KEY" ``` 2. Modify the `schema.prisma` file by changing the database provider in the `datasource` block of the `schema.prisma` file located in the `prisma` folder: ```prisma file=prisma/schema.prisma datasource db { // edit-next-line provider = "postgresql" url = env("DATABASE_URL") } ``` 3. Delete the SQLite database files (`dev.db` and `dev.db-journal`) along with the `migrations` folder, all located in the `prisma` directory. This cleans up the existing SQLite setup and prepares your project to migrate to PostgreSQL. 4. Manually create a new migration for the Postgres database by running the `prisma migrate` command: ```terminal npx prisma migrate dev --name init ``` 5. Start the development server again: ```terminal npm run dev ``` 6. Open the Nuxt DevTools (by hitting <kbd>Shift</kbd>+<kbd>Option</kbd>+ <kbd>D</kbd>) and click the Prisma logo in the left sidenav to open Prisma Studio. Then add a new `User` record by specifying values for the `name` and `email` fields. 7. Verify the data in the application by refreshing your application at `https://localhost:3000`. The page should display the name of the user you added in Prisma Studio. For example, if you added a user named `Jon`, the application will display `Jon` in the browser. Congratulations, your Nuxt app is now fully integrated with Prisma Postgres! ## 7. Deploy to Vercel Deploy your Nuxt application with Prisma Postgres integration to Vercel by following these steps: 1. Ensure your project is version-controlled and pushed to a GitHub repository. If you don't have a repository yet, [create one on GitHub](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-new-repository). Once the repository is ready, run the following commands: ```terminal git add . git commit -m "Initial commit with Prisma Postgres integration" git branch -M main git remote add origin https://github.com/<your-username>/<repository-name>.git git push -u origin main ``` :::note Replace `<your-username>` and `<repository-name>` with your GitHub username and the name of your repository. ::: 2. Log in to [Vercel](https://vercel.com/) and navigate to your [Dashboard](https://vercel.com/docs/dashboard-features). 3. Create a new project. Follow Vercel's [Import an existing project](https://vercel.com/docs/getting-started-with-vercel/import) guide, but stop at [step 3](https://vercel.com/docs/getting-started-with-vercel/import#optionally-configure-any-settings) where you will configure environment variables _before_ clicking **Deploy**. 4. Configure the `DATABASE_URL` environment variable: 1. Expand the **Environment variables** section. 2. Add the `DATABASE_URL` environment variable: - **Key**: `DATABASE_URL` - **Value**: Paste your Prisma Postgres connection URL, e.g. by copying it from the `.env` file in your Nuxt project. :::warning Do not deploy without setting the `DATABASE_URL` variable. Your deployment will fail if the application cannot connect to the database. ::: 5. Click the **Deploy** button. Vercel will build your project and deploy it to a live URL. 6. Open the live URL provided by Vercel and verify that your application is working: - If you've added a user in Prisma Studio, their name should appear on the live site. - If no users exist, the application will display: ``` No user has been added yet. ``` 7. To add or manage data: 1. Open Prisma Studio via [the Prisma Data Platform](https://prisma.io/blog/studio-for-prisma-postgres-view-and-edit-your-data-online) or local instance. 2. Add or update user data in the database. 3. Refresh your live site to confirm the changes. Congratulations! Your Nuxt application with Prisma Postgres integration is now live and fully operational on Vercel. ## Considerations This guide helps you get started with Prisma Postgres using the Nuxt module. Because the Nuxt module is actively evolving, it does not cover all of Prisma's features or support every edge case. For more advanced functionality or edge deployments, consider using Prisma directly. --- # How to use Prisma in Docker URL: https://www.prisma.io/docs/guides/docker This guide walks you through setting up a Prisma ORM application within a Docker environment. You'll learn how to configure a Node.js project, integrate Prisma for database management, and orchestrate the application using Docker Compose. By the end, you'll have a fully functional Prisma application running in a Docker container. ## Prerequisites - [Docker](https://docs.docker.com/) and [Docker Compose](https://docs.docker.com/compose/) installed - Node.js version: A [compatible Node.js version](/orm/more/upgrade-guides/upgrading-versions/upgrading-to-prisma-6#minimum-supported-nodejs-versions), required for Prisma 6. Before starting, ensure that no PostgreSQL services are running locally, and that the following ports are free to avoid conflicts: `5432` (PostgreSQL), `3000` (application server) or `5555` (Prisma Studio server). To stop existing PostgreSQL services, use: ```terminal sudo systemctl stop postgresql # Linux brew services stop postgresql # macOS net stop postgresql # Windows (Run as Administrator) ``` To stop all running Docker containers and free up ports: ```terminal docker ps -q | xargs docker stop ``` ## 1. Set up your Node.js and Prisma application Let's start by creating a simple Node.js application with Prisma ORM and [Express.js](https://expressjs.com/). ### 1.1. Initialize your project First, create a new project directory and initialize a Node.js project: ```terminal mkdir docker-test cd docker-test npm init -y ``` This will generate a `package.json` file: ```json file=package.json { "name": "docker-test", "version": "1.0.0", "description": "", "main": "index.js", "scripts": {}, "keywords": [], "author": "", "license": "ISC" } ``` ### 1.2. Install required dependencies Next, install the Prisma CLI as a development dependency and Express.js for the server: ```terminal npm install prisma --save-dev npm install express ``` ### 1.3. Set up Prisma ORM Now, initialize Prisma to generate the necessary files: ```terminal npx prisma init --output ../generated/prisma ``` This creates: - A `prisma` folder containing `schema.prisma`, where you will define your database schema. - An `.env` file in the project root, which stores environment variables. Add a `User` model to the `schema.prisma` file located in the `prisma/schema.prisma` folder: ```prisma file=prisma/schema.prisma datasource db { provider = "postgresql" url = env("DATABASE_URL") } generator client { provider = "prisma-client-js" //add-start output = "../generated/prisma_client" //add-end } //add-start model User { id Int @id @default(autoincrement()) createdAt DateTime @default(now()) email String @unique name String? } //add-end ``` :::note In the `schema.prisma` file, we specify a [custom `output` path](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path) where Prisma will generate its types. This ensures Prisma's types are resolved correctly across different package managers and can be accessed by application consistently inside the container without any permission issues. In this guide, the types will be generated in the `./generated/prisma_client` directory. ::: ### 1.4. Create an Express.js server With the Prisma schema in place, let's create an Express.js server to interact with the database. Start by creating an `index.js` file: ```terminal touch index.js ``` Add the following code to set up a basic Express server: ```js file=index.js //add-start const express = require("express"); const { PrismaClient } = require("./generated/prisma_client"); const app = express(); const prisma = new PrismaClient(); app.use(express.json()); // Get all users app.get("/", async (req, res) => { const userCount = await prisma.user.count(); res.json( userCount == 0 ? "No users have been added yet." : "Some users have been added to the database." ); }); const PORT = 3000; app.listen(PORT, () => { console.log(`Server is running on http://localhost:${PORT}`); }); //add-end ``` Update the `package.json` scripts to include commands for running the server and deploying migrations: ```json file=package.json "scripts": { //delete-start "test": "echo \"Error: no test specified\" && exit 1", //delete-end //add-start "dev": "node index.js", "db:deploy": "npx prisma migrate deploy && npx prisma generate" //add-end } ``` Now that the application is set up, let's move on to configuring a PostgreSQL database using Docker Compose. ## 2. Set up a PostgreSQL database with Docker Compose To perform database migrations, we'll create a standalone PostgreSQL database using Docker Compose. ### 2.1. Create a Docker Compose file for PostgreSQL Create a `docker-compose.postgres.yml` file in the root directory: ```yml file=docker-compose.postgres.yml // add-start version: '3.7' services: postgres: image: postgres:15 restart: always environment: - POSTGRES_DB=postgres - POSTGRES_USER=postgres - POSTGRES_PASSWORD=prisma ports: - "5432:5432" networks: - prisma-network healthcheck: test: ["CMD-SHELL", "pg_isready -U prisma -d postgres"] interval: 5s timeout: 2s retries: 20 volumes: - postgres_data:/var/lib/postgresql/data command: postgres -c listen_addresses='*' logging: options: max-size: "10m" max-file: "3" networks: prisma-network: volumes: postgres_data: // add-end ``` ### 2.2. Start the PostgreSQL container Run the following command to start the database: ```terminal docker compose -f docker-compose.postgres.yml up -d ``` ### 2.3. Perform database migrations With the database running, update the `.env` file with the following database connection url: ```.env file=.env // edit-next-line DATABASE_URL="postgresql://postgres:prisma@localhost:5432/postgres?schema=public" ``` Run the migration to create the database schema: ```terminal npx prisma migrate dev --name init ``` This should generate a `migrations` folder in the `prisma` folder. ### 2.4. Test the application Start the server and verify it works: ```termial npm run dev ``` Visit [`http://localhost:3000`](http://localhost:3000) to see the message: ```terminal No users have been added yet. ``` Stop the local server. ### 2.5. Clean up the standalone database Once testing is complete, remove the standalone PostgreSQL container: ```terminal docker compose -f docker-compose.postgres.yml down --remove-orphans ``` This command will: - Stop running containers. - Remove containers. - Remove the default network created by Docker Compose. - Remove associated volumes (if not named explicitly). Now that we've tested the application locally, let's containerize it using Docker. ## 3. Run the app and database together with Docker Compose We'll now containerize the application using Docker, ensuring it can run in any environment. To do that create a `Dockerfile` in project root: ```terminal touch Dockerfile ``` For the next step, you'll need to choose between two options for the base image: `node:alpine` (lightweight) or `node:slim` (stable). Both options are fully supported by Prisma ORM, but may have to be configured differently. ### 3.1. Option 1: Use Linux Alpine (`node:alpine`) as a base image The node:alpine image is based on Alpine Linux, a lightweight Linux distribution that uses the `musl` C standard library. It's perfect if you want to keep your container small and efficient. Prisma supports Alpine on `amd64` out of the box, and supports it on `arm64` since `prisma@4.10.0`. Add the following content to the `Dockerfile`: ```shell file=Dockerfile FROM node:lts-alpine3.17 WORKDIR /usr/src/app COPY package.json package-lock.json ./ RUN npm ci COPY . . CMD ["sh", "-c", "npm run db:deploy && npm run dev"] ``` :::note When running on Linux Alpine, Prisma downloads engines that are compiled for the `musl` C standard library. Please don't install `glibc` on Alpine (e.g., via the `libc6-compat` package), as that would prevent Prisma from running successfully. ::: Related Docker images: - `node:lts-alpine` - `node:16-alpine` - `node:14-alpine` ### 3.1. Option 2: Use Linux Debian (`node:slim`) as a base image The `node:slim` image is based on Linux Debian, a stable and widely supported distribution that uses the `glibc` C standard library. It is mostly supported out of the box on `amd64` and `arm64`, making it a good choice if you're running into compatibility issues with Alpine or need a more production-ready environment. However, some older versions of this image may come without `libssl` installed, so it's sometimes necessary to install it manually. Add the following content to the `Dockerfile`: ```shell file=Dockerfile FROM node:slim RUN apt-get update -y \ && apt-get install -y openssl WORKDIR /usr/src/app COPY package.json package-lock.json ./ COPY . . RUN npm ci CMD ["sh", "-c", "npm run db:deploy && npm run dev"] ``` Related Docker images: - `node:lts-slim` - `node:bullseye-slim` - `node:buster-slim` - `node:stretch-slim` ### 3.2. Create and configure a Docker Compose file Now that the `Dockerfile` is ready, we'll use Docker Compose to manage both the app and the database together. This makes it easy to start, stop, and manage the entire setup. Create a `docker-compose.yml` file in your project folder: ```terminal touch docker-compose.yml ``` Add the following configuration to the file: ```yml file=docker-compose.yml // add-start version: '3.7' services: postgres_db: image: postgres:15 hostname: postgres_db container_name: postgres_db restart: always environment: POSTGRES_DB: postgres POSTGRES_USER: postgres POSTGRES_PASSWORD: prisma ports: - '5432:5432' networks: - prisma-network healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"] interval: 5s timeout: 2s retries: 20 server: build: context: . dockerfile: Dockerfile ports: - '3000:3000' stdin_open: true tty: true # Keeps the container running for debugging depends_on: postgres_db: condition: service_healthy env_file: - .env.prod networks: - prisma-network networks: prisma-network: name: prisma-network // add-end ``` ### 3.3. Configure environment variable for the container Before running the app, we need to configure the environment variables. Create a `.env.prod` file: ``` touch .env.prod ``` Add the following database connection url to the `.env.prod` file: ```.env file=.env.prod // edit-next-line DATABASE_URL="postgresql://postgres:prisma@postgres_db:5432/postgres?schema=public" ``` ### 3.4. Build and run the application With everything set up, it's time to build and run the app using Docker Compose. Run the following command: ```terminal docker compose -f docker-compose.yml up --build -d ``` Visit `http://localhost:3000` to see your app running with the message: ```terminal No users have been added yet. ``` ### 3.5. Bonus: Add Prisma Studio for database management [Prisma Studio](/orm/tools/prisma-studio) offers a graphical user interface (GUI) that allows you to view and manage your database directly in the browser. It's a great tool for debugging and managing your data during development. To add Prisma Studio to your Docker setup, update the `docker-compose.yml` file: ```yml file=docker.compose.yml version: '3.7' services: postgres_db: image: postgres:15 hostname: postgres_db container_name: postgres_db restart: always environment: POSTGRES_DB: postgres POSTGRES_USER: postgres POSTGRES_PASSWORD: prisma ports: - '5432:5432' networks: - prisma-network healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"] interval: 5s timeout: 2s retries: 20 server: build: context: . dockerfile: Dockerfile ports: - '3000:3000' stdin_open: true tty: true # Keeps the container running for debugging depends_on: postgres_db: condition: service_healthy env_file: - .env.prod networks: - prisma-network // add-start prisma-studio: image: node:lts-alpine3.17 working_dir: /usr/src/app volumes: - .:/usr/src/app command: npx prisma studio --port 5555 --browser none ports: - "5555:5555" env_file: - .env.prod networks: - prisma-network depends_on: postgres_db: condition: service_healthy server: condition: service_started // add-end networks: prisma-network: name: prisma-network ``` This will start Prisma Studio at [`http://localhost:5555`](http://localhost:5555) alongside the main app at [`http://localhost:3000`](http://localhost:3000). You can use Prisma Studio to manage your database with a GUI. Run the following command to start everything: ```terminal docker compose -f docker-compose.yml up --build -d ``` By following this guide, you've successfully containerized your Prisma app and database using Docker Compose. --- # How to use Prisma ORM in a pnpm workspaces monorepo URL: https://www.prisma.io/docs/guides/use-prisma-in-pnpm-workspaces Prisma is a powerful ORM for managing your database, and when combined with [pnpm Workspaces](https://pnpm.io/workspaces), you can maintain a lean and modular monorepo architecture. In this guide, we’ll walk through setting up Prisma in its own package within a pnpm Workspaces monorepo, enabling maintainable type sharing and efficient database management across your apps. ### What you'll learn: - How to initialize a monorepo using pnpm Workspaces. - Steps to integrate Prisma as a standalone package. - How to generate and share the Prisma Client across packages. - Integrating the Prisma package into an application within your workspace. ## 1. Prepare your project and configure pnpm workspaces Before integrating Prisma, you need to set up your project structure. Start by creating a new directory for your project (for example, `my-monorepo`) and initialize a Node.js project: ```terminal mkdir my-monorepo cd my-monorepo pnpm init ``` Next, create a `pnpm-workspace.yaml` file to define your workspace structure and pin the Prisma version: ```terminal touch pnpm-workspace.yaml ``` Add the following configuration to `pnpm-workspace.yaml`: ```yaml file=pnpm-workspace.yaml packages: - "apps/*" - "packages/*" catalogs: prisma: prisma: latest ``` :::note The `catalogs` help you pin a certain version of prisma across your repositories. You can learn more about them [here](https://pnpm.io/catalogs). *Explictly* pin the lastest version of [prisma](https://www.npmjs.com/package/prisma) in the `pnpm-workspace.yaml` file. At the time of writing, this is version `6.3.1`. ::: Finally, create directories for your applications and shared packages: ```terminal mkdir apps mkdir -p packages/database ``` ## 2. Setup the shared database package This section covers creating a standalone database package that uses Prisma. The package will house all database models and the generated Prisma Client, making it reusable across your monorepo. ### 2.1. Initialize the package and install dependencies Navigate to the `packages/database` directory and initialize a new package: ```terminal cd packages/database pnpm init ``` Add Prisma as a development dependency in your `package.json` using the pinned `catalog`: ```json file=database/package.json // add-start "devDependencies": { "prisma": "catalog:prisma" } // add-end ``` Then install Prisma: ```terminal pnpm install ``` Then, add additional dependencies: ```terminal pnpm add typescript tsx @types/node -D ``` Then install the Prisma Client extension required to use Prisma Postgres: ```terminal pnpm add @prisma/extension-accelerate ``` :::info This guide uses [Prisma Postgres](/postgres/getting-started). If you plan to use a different database, you can omit the [@prisma/extension-accelerate package](https://www.npmjs.com/package/@prisma/extension-accelerate/). ::: Initalize a `tsconfig.json` file for your `database` package: ```terminal pnpm tsc --init ``` ### 2.2. Setup Prisma ORM in your database package Initialize Prisma ORM with an instance of [Prisma Postgres](/postgres) in the `database` package by running the following command: ```terminal pnpm prisma init --db ``` Enter a name for your project and choose a database region. :::info We're going to be using [Prisma Postgres](/postgres/getting-started) in this guide. If you're not using a Prisma Postgres database, you won't need to add the `--db` flag. ::: This command: - Connects your CLI to your [Prisma Data Platform](https://console.prisma.io) account. If you're not logged in or don't have an account, your browser will open to guide you through creating a new account or signing into your existing one. - Creates a `prisma` directory containing a `schema.prisma` file for your database models. - Creates a `.env` file with your `DATABASE_URL` (e.g., for Prisma Postgres it should have something similar to `DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI..."`). Edit the `schema.prisma` file to define a `User` model in your database and specify a [custom `output` directory](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path) to generate the Prisma Client. This ensures that generated types are resolved correctly: ```prisma file=prisma/schema.prisma generator client { provider = "prisma-client-js" //add-start output = "../generated/client" //add-end } datasource db { provider = "postgresql" url = env("DATABASE_URL") } //add-start model User { id Int @id @default(autoincrement()) email String @unique name String? } //add-end ``` Next, add helper scripts to your `package.json` to simplify Prisma commands: ```json file=database/package.json { "scripts": { // delete-start "test": "echo \"Error: no test specified\" && exit 1", // delete-end // add-start "db:generate": "prisma generate --no-engine", "db:migrate": "prisma migrate dev", "db:deploy": "prisma migrate deploy", "db:studio": "prisma studio" // add-end } } ``` :::info If you're not using [Prisma Postgres](/postgres/getting-started) for your database, exclude the `--no-engine` flag from the `db:generate` script. ::: Use [Prisma Migrate](/orm/prisma-migrate) to migrate your database changes: ```terminal pnpm run db:migrate ``` When prompted by the CLI, enter a descriptive name for your migration. Once the migration is successful, create a `client.ts` file to initialize Prisma Client with the Accelerate extension: ```ts file=database/client.ts // add-start import { PrismaClient } from "./generated/client"; import { withAccelerate } from '@prisma/extension-accelerate' const prisma = new PrismaClient().$extends(withAccelerate()) const globalForPrisma = global as unknown as { prisma: typeof prisma } if (process.env.NODE_ENV !== 'production') globalForPrisma.prisma = prisma export { prisma }; // add-end ``` :::info If you're not using [Prisma Postgres](/postgres/getting-started) for your database, exclude the `import { withAccelerate }` line and `.$extends(withAccelerate())` from the line following it. ::: Then, create an `index.ts` file to re-export the instance of Prisma Client and all generated types: ```ts file=database/index.ts // add-start export { prisma } from "./client"; export * from "./generated/client"; // add-end ``` At this point, your shared database package is fully configured and ready for use across your monorepo. ## 3. Set up and integrate your frontend application Now that the database package is set up, create a frontend application (using Next.js) that uses the shared Prisma Client to interact with your database. ### 3.1. Bootstrap a Next.js application Navigate to the `apps` directory: ```terminal cd ../../apps ``` Create a new Next.js app named `web`: ```terminal pnpm create next-app@latest web --yes ``` :::note[important] The `--yes` flag uses default configurations to bootstrap the Next.js app (which in this guide uses the app router without a `src/` directory and `pnpm` as the installer). Additionally, the flag may automatically initialize a Git repository in the `web` folder. If that happens, please remove the `.git` directory by running `rm -r .git`. ::: Then, navigate into the web directory: ```terminal cd web/ ``` Copy the `.env` file from the database package to ensure the same environment variables are available: ```terminal cp ../../packages/database/.env . ``` Open the `package.json` file of your Next.js app and add the shared `database` package as a dependency: ```json file=web/package.json "dependencies": { // add-start "database": "workspace:*", // add-end // additional dependencies // ... } ``` Run the following command to install the `database` package: ```terminal pnpm install ``` ### 3.2. Integrate the shared `database` package in your app code Modify your Next.js application code to use Prisma Client from the database package. Update `app/page.tsx` as follows: ```tsx file=app/page.tsx // add-start import { prisma } from "database"; export default async function Home() { const user = await prisma.user.findFirst({ select: { name: true } }) return ( <div> {user?.name && <p>Hello from {user.name}</p>} {!user?.name && <p>No user has been added to the database yet. </p>} </div> ); } // add-end ``` This code demonstrates importing and using the shared Prisma Client to query your `User` model. ### 3.3. Add helper scripts and run your application Add the following scripts to the root `package.json` of your monorepo. They ensure that database migrations, type generation, and app builds run in the proper order: ```package.json "scripts": { // add-start "build": "pnpm --filter database db:deploy && pnpm --filter database db:generate && pnpm --filter web build", "start": "pnpm --filter web start", "dev": "pnpm --filter database db:generate && pnpm --filter web dev", "studio": "pnpm --filter database db:studio" // add-end } ``` ### 3.4. Run your application Then head back to the root of the monorepo: ```terminal cd ../../ ``` Start your development server by executing: ```terminal pnpm run dev ``` Open your browser at [`http://localhost:3000`](http://localhost:3000) to see your app in action. ### 3.5. (Optional) Add data to your database using Prisma Studio There shouldn't be data in your database yet. You can execute `pnpm run studio` in your CLI to start a [Prisma Studio](/orm/tools/prisma-studio) in [`http://localhost:5555`](http://localhost:5555) to interact with your database and add data to it. ## Next Steps You have now created a monorepo that uses Prisma ORM effectively, with a shared database package integrated into a Next.js application. For further exploration and to enhance your setup, consider reading the [How to use Prisma ORM with Turborepo](/guides/turborepo) guide. --- # How to use multiple databases in a single app URL: https://www.prisma.io/docs/guides/multiple-databases ## Introduction This guide shows you how to use multiple databases using Prisma ORM in a single [Next.js app](https://nextjs.org/). You will learn how to connect to two different Prisma Postgres databases, manage migrations, and deploy your application to Vercel. This approach is useful for multi-tenant applications or when you need to separate concerns when managing connections to multiple databases. ## Prerequisites Before you begin, make sure that you have the following: - Node.js 18+ installed. - A [Prisma Data Platform account](https://pris.ly/pdp?utm_campaign=multi-client&utm_source=docs). - A Vercel account (if you plan to deploy your application). ## 1. Set up a Next.js project Create a new Next.js app using `create-next-app` from your desired directory: ```terminal npx create-next-app@latest my-multi-client-app ``` You will be prompted to answer a few questions about your project. Select all of the defaults. :::info For completeness, those are: - TypeScript - ESLint - Tailwind CSS - No `src` directory - App Router - Turbopack - Default custom import alias: `@/*` ::: Then, navigate to the project directory: ```terminal cd my-multi-client-app ``` ## 2. Set up your databases and Prisma Clients In this section, you will create two separate Prisma Postgres instances—one for user data and one for post data. You will also configure the Prisma schema and environment variables for each. First, install Prisma as a development dependency: ```terminal npm install -D prisma ``` Install the [Prisma Client extension](https://www.npmjs.com/package/@prisma/extension-accelerate) that is required to use Prisma Postgres: ```terminal npm install @prisma/extension-accelerate ``` :::info If you are not using a Prisma Postgres database, you won't need the `@prisma/extension-accelerate` package. ::: You have installed the required dependencies for the project. ### 2.1. Create a Prisma Postgres instance to contain user data Initialize Prisma with a [Prisma Postgres](/postgres) instance by running: ```terminal npx prisma@latest init --db ``` :::info If you are not using a Prisma Postgres database, do not use the `--db` flag. Instead, create two PostgreSQL database instances and add their connection URLs to the `.env` file as `PPG_USER_DATABASE_URL` and `PPG_POST_DATABASE_URL`. ::: Follow the prompts to name your project and choose a database region. The `prisma@latest init --db` command: - Connects your CLI to your [Prisma Data Platform](https://console.prisma.io) account. If you are not logged in or do not have an account, your browser will open to guide you through creating a new account or signing into your existing one. - Creates a `prisma` directory containing a `schema.prisma` file for your database models. - Creates a `.env` file with your `DATABASE_URL` (e.g., for Prisma Postgres it should have something similar to `DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI..."`). Rename the `prisma` folder to `prisma-user-database`: ```terminal mv prisma prisma-user-database ``` Edit your `.env` file to rename `DATABASE_URL` to `PPG_USER_DATABASE_URL`: ```text file=.env //delete-start DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI... //delete-end //add-start PPG_USER_DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI... //add-end ``` Open `prisma-user-database/schema.prisma` file and update it to define a `User` model. Also, set the environment variable and specify a [custom `output` directory](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path) for the generated Prisma Client: ```prisma file=prisma-user-database/schema.prisma generator client { provider = "prisma-client-js" //add-start output = "../prisma-user-database/user-database-client-types" //add-end } datasource db { provider = "postgresql" //delete-start url = env("DATABASE_URL") //delete-end //add-start url = env("PPG_USER_DATABASE_URL") //add-end } //add-start model User { id Int @id @default(autoincrement()) email String @unique name String? } //add-end ``` Your user database schema is now ready. ### 2.2. Create a Prisma Postgres instance for post data Repeat the initialization for the post database: ```terminal npx prisma init --db ``` After following the prompts, rename the new `prisma` folder to `prisma-post-database`: ```terminal mv prisma prisma-post-database ``` Rename the `DATABASE_URL` variable in `.env` to `PPG_POST_DATABASE_URL`: ```text file=.env //delete-start DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI... //delete-end //add-start PPG_POST_DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=eyJhbGciOiJIUzI... //add-end ``` Edit the `prisma-post-database/schema.prisma` file to define a `Post` model. Also, update the datasource URL and set a [custom `output` directory](/orm/prisma-client/setup-and-configuration/generating-prisma-client#using-a-custom-output-path): ```prisma file=prisma-post-database/schema.prisma generator client { provider = "prisma-client-js" //add-start output = "../prisma-post-database/post-database-client-types" //add-end } datasource db { provider = "postgresql" //delete-start url = env("DATABASE_URL") //delete-end //add-start url = env("PPG_POST_DATABASE_URL") //add-end } //add-start model Post { id Int @id @default(autoincrement()) title String content String? } //add-end ``` Your post database schema is now set. ### 2.3. Add helper scripts and migrate the schemas To simplify your workflow, add helper scripts to your `package.json` file that run Prisma commands for both databases: ```json file=package.json "script":{ "dev": "next dev --turbopack", "build": "next build", "start": "next start", "lint": "next lint", // add-start "postinstall": "npx prisma generate --schema ./prisma-user-database/schema.prisma --no-engine && npx prisma generate --schema ./prisma-post-database/schema.prisma --no-engine", "generate": "npx prisma generate --schema ./prisma-user-database/schema.prisma --no-engine && npx prisma generate --schema ./prisma-post-database/schema.prisma --no-engine", "migrate": "npx prisma migrate dev --schema ./prisma-user-database/schema.prisma && npx prisma migrate dev --schema ./prisma-post-database/schema.prisma", "deploy": "npx prisma migrate deploy --schema ./prisma-user-database/schema.prisma && npx prisma migrate deploy --schema ./prisma-post-database/schema.prisma", "studio": "npx prisma studio --schema ./prisma-user-database/schema.prisma --port 5555 & npx prisma studio --schema ./prisma-post-database/schema.prisma --port 5556" // add-end } ``` :::info If you are not using a Prisma Postgres database, remove the `--no-engine` flag from the custom scripts above. ::: Here is an explanation of the custom scripts: - `postinstall`: Runs immediately after installing dependencies to generate Prisma Clients for both the user and post databases using their respective schema files. - `generate`: Manually triggers the generation of Prisma Clients for both schemas, ensuring your client code reflects the latest models. - `migrate`: Applies pending migrations in development mode for both databases using [Prisma Migrate](/orm/prisma-migrate), updating their schemas based on changes in your Prisma files. - `deploy`: Executes migrations in a production environment, synchronizing your live databases with your Prisma schemas. - `studio`: Opens Prisma Studio for both databases simultaneously on different ports (`5555` for the user database and `5556` for the post database) for visual data management. Run the migrations: ```terminal npm run migrate ``` When prompted, name the migration for each database accordingly. ## 3. Prepare the application to use multiple Prisma Clients Next, create a `lib` folder to store helper files for instantiating and exporting your Prisma Clients: ```terminal mkdir -p lib && touch lib/user-prisma-client.ts lib/post-prisma-client.ts ``` ### 3.1. Instantiate and export the Prisma Client for the user database In `lib/user-prisma-client.ts`, add the following code: ```ts file=lib/user-prisma-client.ts //add-start import { PrismaClient } from "../prisma-user-database/user-database-client-types"; import { withAccelerate } from "@prisma/extension-accelerate" const getPrisma = () => new PrismaClient().$extends(withAccelerate()); const globalForUserDBPrismaClient = global as unknown as { userDBPrismaClient: ReturnType<typeof getPrisma>; }; export const userDBPrismaClient = globalForUserDBPrismaClient.userDBPrismaClient || getPrisma(); if (process.env.NODE_ENV !== "production") globalForUserDBPrismaClient.userDBPrismaClient = userDBPrismaClient; //add-end ``` :::info If you are not using a Prisma Postgres database, do not extend `PrismaClient` with the `withAccelerate` client extension. ::: ### 3.2. Instantiate and export the Prisma Client for the post database In `lib/post-prisma-client.ts`, add this code: ```ts file=lib/post-prisma-client.ts //add-start import { PrismaClient } from "../prisma-post-database/post-database-client-types"; import { withAccelerate } from "@prisma/extension-accelerate" const getPrisma = () => new PrismaClient().$extends(withAccelerate()); const globalForPostDBPrismaClient = global as unknown as { postDBPrismaClient: ReturnType<typeof getPrisma>; }; export const postDBPrismaClient = globalForPostDBPrismaClient.postDBPrismaClient || getPrisma(); if (process.env.NODE_ENV !== "production") globalForPostDBPrismaClient.postDBPrismaClient = postDBPrismaClient; //add-end ``` :::info If you are not using a Prisma Postgres database, do not extend `PrismaClient` with the `withAccelerate` client extension. ::: ## 4. Integrate multiple Prisma Clients in your Next.js app Modify your application code to fetch data from both databases. Update the `app/page.tsx` file as follows: ```ts file=app/page.tsx //add-start import { postDBPrismaClient } from "@/lib/post-prisma-client"; import { userDBPrismaClient } from "@/lib/user-prisma-client"; export default async function Home() { const user = await userDBPrismaClient.user.findFirst(); const post = await postDBPrismaClient.post.findFirst(); return ( <main className="min-h-screen bg-gray-50 py-12"> <div className="max-w-4xl mx-auto px-4"> <header className="mb-12 text-center"> <h1 className="text-5xl font-extrabold text-gray-900">Multi-DB Showcase</h1> <p className="mt-4 text-xl text-gray-600"> Data fetched from two distinct databases. </p> </header> <section className="mb-8 bg-white shadow-md rounded-lg p-6"> <h2 className="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4"> User Data </h2> <pre className="whitespace-pre-wrap text-sm text-gray-700"> {user ? JSON.stringify(user, null, 2) : "No user data available."} </pre> </section> <section className="bg-white shadow-md rounded-lg p-6"> <h2 className="text-2xl font-semibold text-gray-800 border-b pb-2 mb-4"> Post Data </h2> <pre className="whitespace-pre-wrap text-sm text-gray-700"> {post ? JSON.stringify(post, null, 2) : "No post data available."} </pre> </section> </div> </main> ); } //add-end ``` ### 4.1. Populate your databases with data In a separate terminal window, open two instances of [Prisma Studio](/orm/tools/prisma-studio) to add data to your databases by running the script: ```terminal npm run studio ``` This will open up two browser windows, one in `http://localhost:5555` and one in `http://localhost:5556`. Navigate to those windows and add sample data to both databases. ### 4.2. Run the development server Before starting the development server, note that if you are using Next.js `v15.2.0`, do not use Turbopack as there is a known [issue](https://github.com/vercel/next.js/issues/76497). Remove Turbopack from your dev script by updating your `package.json`: ```json file=package.json "script":{ //delete-start "dev": "next dev --turbopack", //delete-end //add-start "dev": "next dev", //add-end "build": "next build", "start": "next start", "lint": "next lint", "postinstall": "npx prisma generate --schema ./prisma-user-database/schema.prisma --no-engine && npx prisma generate --schema ./prisma-post-database/schema.prisma --no-engine", "generate": "npx prisma generate --schema ./prisma-user-database/schema.prisma --no-engine && npx prisma generate --schema ./prisma-post-database/schema.prisma --no-engine", "migrate": "npx prisma migrate dev --schema ./prisma-user-database/schema.prisma && npx prisma migrate dev --schema ./prisma-post-database/schema.prisma", "deploy": "npx prisma migrate deploy --schema ./prisma-user-database/schema.prisma && npx prisma migrate deploy --schema ./prisma-post-database/schema.prisma", "studio": "npx prisma studio --schema ./prisma-user-database/schema.prisma --port 5555 & npx prisma studio --schema ./prisma-post-database/schema.prisma --port 5556" } ``` In a separate terminal window, start the development server by running: ```terminal npm run dev ``` Navigate to `http://localhost:3000` to see your Next.js app display data from both databases: ![App displaying data by querying two separate database instances](/img/guides/multi-client-app-demo.png) Congratulations, you have a Next.js app running with two Prisma Client instances querying different databases. ## 5. Deploy your Next.js app using multiple databases to Vercel Deploy your app by following these steps: 1. Ensure your project is version-controlled and pushed to a GitHub repository. If you do not have a repository yet, [create one on GitHub](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-new-repository). Once the repository is ready, run the following commands: ```terminal git add . git commit -m "Initial commit with Prisma Postgres integration" git branch -M main git remote add origin https://github.com/<your-username>/<repository-name>.git git push -u origin main ``` :::note Replace `<your-username>` and `<repository-name>` with your GitHub username and the name of your repository. ::: 2. Log in to [Vercel](https://vercel.com/) and navigate to your [Dashboard](https://vercel.com/docs/dashboard-features). 3. Create a new project. Follow Vercel's [Import an existing project](https://vercel.com/docs/getting-started-with-vercel/import) guide, but stop at [step 3](https://vercel.com/docs/getting-started-with-vercel/import#optionally-configure-any-settings) where you will configure environment variables _before_ clicking **Deploy**. 4. Configure the `DATABASE_URL` environment variable: 1. Expand the **Environment variables** section. 1. Add the `PPG_USER_DATABASE_URL` environment variable: - **Key**: `PPG_USER_DATABASE_URL` - **Value**: Paste your user database connection URL, e.g. by copying it from the `.env` file in your project. 1. Add the `PPG_POST_DATABASE_URL` environment variable: - **Key**: `PPG_POST_DATABASE_URL` - **Value**: Paste your post database connection URL, e.g. by copying it from the `.env` file in your project. :::warning Do not deploy without setting the environment variables. Your deployment will fail if the application cannot connect to the databases. ::: 5. Click the **Deploy** button. Vercel will build your project and deploy it to a live URL. Open the live URL provided by Vercel and verify that your application is working. Congratulations! You have deployed an application that uses multiple Prisma Clients to query two different databases, and it is now live and fully operational on Vercel. ## Next steps In this guide, you learned how to use multiple databases using Prisma ORM in a single Next.js app by: - Setting up separate Prisma schemas for user and post databases. - Configuring custom output directories and environment variables. - Creating helper scripts to generate and migrate each schema. - Instantiating and integrating multiple Prisma Clients into your application. - Deploying your multi-database application to Vercel. This approach allows you to maintain a clear separation of data models and simplifies multi-tenant or multi-database scenarios. For further improvements in managing your project, consider using a monorepo setup. Check out our related guides: - [How to use Prisma ORM in a pnpm workspaces monorepo](/guides/use-prisma-in-pnpm-workspaces) - [How to use Prisma ORM with Turborepo](/guides/turborepo) --- # How to use Prisma ORM with TanStack Start URL: https://www.prisma.io/docs/guides/tanstack-start ## Introduction Prisma ORM simplifies database interactions, and [TanStack Start](https://tanstack.com/start/latest/docs/framework/react/overview) offers a robust framework for building modern React applications. Together with [Prisma Postgres](https://www.prisma.io/postgres), they provide a seamless full-stack development experience with type-safe queries and efficient data management. This guide will walk you through integrating Prisma ORM with a Prisma Postgres database in a TanStack Start project from scratch. ## Prerequisites Before starting this guide, ensure you have: - Node.js 18+ installed - A [Prisma Postgres](https://www.prisma.io/postgres) database (or any PostgreSQL database) ## Step 1: Initialize Your TanStack Start Project To begin, create a new TanStack Start project. In the directory where you'd like to create your project, run the following commands: ```terminal mkdir tanstack-start-prisma cd tanstack-start-prisma npm init -y ``` This will create a new folder called `tanstack-start-prisma`, navigate into it, and initialize a new Node.js project. Open the directory in your IDE and create a `tsconfig.json` file with the following configuration: ```json file=tsconfig.json showLineNumbers { "compilerOptions": { "jsx": "react-jsx", "moduleResolution": "Bundler", "module": "ESNext", "target": "ES2022", "skipLibCheck": true, "strictNullChecks": true } } ``` We also need a `.gitignore` file, so let's set that up now: ```txt file=.gitignore showLineNumbers node_modules .env ``` Next, install TanStack Router and Vinxi, as TanStack Start currently requires them: ```terminal npm install @tanstack/react-start @tanstack/react-router vinxi ``` We also need React, the Vite React plugin, and TypeScript: ```terminal npm install react react-dom npm install --save-dev @vitejs/plugin-react vite-tsconfig-paths npm install --save-dev typescript @types/react @types/react-dom ``` Update your `package.json` to use Vinxi's CLI. Add `"type": "module"` and modify the scripts to use Vinxi's CLI: ```json file=package.json showLineNumbers { "type": "module", "scripts": { "dev": "vinxi dev", "build": "vinxi build", "start": "vinxi start" } } ``` Then, create and configure TanStack Start's `app.config.ts` file: ```typescript file=app.config.ts showLineNumbers import { defineConfig } from '@tanstack/react-start/config' import tsConfigPaths from 'vite-tsconfig-paths' export default defineConfig({ vite: { plugins: [ tsConfigPaths({ projects: ['./tsconfig.json'], }), ], }, }) ``` For TanStack Start to function, we need 5 files in `~/app/`: - `router.tsx` (The router configuration) - `ssr.tsx` (The server entry point) - `client.tsx` (The client entry point) - `routes/__root.tsx` (The root of the app) - `routes/index.tsx` (The home page) `router.tsx` configures the application's main router with route definitions and settings: ```typescript file=app/router.tsx showLineNumbers import { createRouter as createTanStackRouter } from '@tanstack/react-router' import { routeTree } from './routeTree.gen' export function createRouter() { const router = createTanStackRouter({ routeTree, scrollRestoration: true, }) return router } declare module '@tanstack/react-router' { interface Register { router: ReturnType<typeof createRouter> } } ``` :::note You should be seeing an error about `routeTree.gen.ts` not existing. This is expected. It will be generated when you run TanStack Start for the first time. ::: `ssr.tsx` allows us to know what routes and loaders we need to execute when the user hits a given route: ```typescript file=app/ssr.tsx showLineNumbers import { createStartHandler, defaultStreamHandler, } from '@tanstack/react-start/server' import { getRouterManifest } from '@tanstack/react-start/router-manifest' import { createRouter } from './router' export default createStartHandler({ createRouter, getRouterManifest, })(defaultStreamHandler) ``` `client.tsx` initializes the client-side logic to handle routes in the browser: ```typescript file=app/client.tsx showLineNumbers import { hydrateRoot } from "react-dom/client"; import { StartClient } from "@tanstack/react-start/client"; import { createRouter } from "./router"; const router = createRouter(); hydrateRoot(document, <StartClient router={router} />); ``` `routes/__root.tsx` defines the root route and global HTML layout for the entire application: ```typescript file=app/routes/__root.tsx showLineNumbers import type { ReactNode } from "react"; import { Outlet, createRootRoute, HeadContent, Scripts, } from "@tanstack/react-router"; export const Route = createRootRoute({ head: () => ({ meta: [ { charSet: "utf-8", }, { name: "viewport", content: "width=device-width, initial-scale=1", }, { title: "Prisma TanStack Start Demo", }, ], }), component: RootComponent, }); function RootComponent() { return ( <RootDocument> <Outlet /> </RootDocument> ); } function RootDocument({ children }: Readonly<{ children: ReactNode }>) { return ( <html> <head> <HeadContent /> </head> <body> {children} <Scripts /> </body> </html> ); } ``` `routes/index.tsx` is the home page of the application: ```typescript file=app/routes/index.tsx showLineNumbers import { createFileRoute } from "@tanstack/react-router"; export const Route = createFileRoute("/")({ component: Home, }); function Home() { return ( <div> <h1>Posts</h1> </div> ); } ``` Now, run: ```terminal npm run dev ``` This will generate the `routeTree.gen.ts` file and resolve any routing errors. Your file tree should look like this: ``` . ├── app/ │ ├── routes/ │ │ ├── __root.tsx │ │ └── index.tsx │ ├── client.tsx │ ├── router.tsx │ ├── routeTree.gen.ts │ └── ssr.tsx ├── .gitignore ├── app.config.ts ├── package-lock.json ├── package.json └── tsconfig.json ``` ## Step 2: Install and Configure Prisma ORM Next, we need to install and set up Prisma ORM in our project. Let's start by installing the Prisma CLI. ### 2.1 Install Prisma ORM and Define Your Model To start, install the necessary dependencies. At the root of your project, run: ```terminal npm install prisma --save-dev npm install @prisma/client ``` The Prisma CLI is now installed. Now, run the following command and follow the prompts to set up Prisma: ```terminal npx prisma init --db --output ../app/generated/prisma ``` This command does the following: - Creates a `prisma` directory with a `schema.prisma` file. - Creates a Prisma Postgres database. - Creates a `.env` file containing the `DATABASE_URL` at the project root. - Defines the output directory for the generated Prisma Client into `app/generated/prisma`. In `schema.prisma`, create a model for our Posts and change the generator to use the `prisma-client` provider: ```prisma file=prisma/schema.prisma showLineNumbers generator client { //add-next-line provider = "prisma-client" //delete-next-line provider = "prisma-client-js" output = "../app/generated/prisma" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } //add-start model Post { id Int @id @default(autoincrement()) title String content String? } //add-end ``` To migrate your database, run: ```terminal npx prisma migrate dev --name init ``` This does three things: - Creates a new SQL migration file in the `prisma/migrations` directory. - Executes the SQL migration file against the database. - Runs `prisma generate` under the hood, which installs the `@prisma/client` package and generates a tailored Prisma Client API based on your models. To view your database, run: ```terminal npx prisma studio ``` Select the `Post` table and add a record. :::info Instead of using Prisma Studio, you can seed your database with data using the following command. See [Prisma Seed](/orm/prisma-migrate/workflows/seeding) for more information. ::: We can't see the post in our app yet, so let's fix that. ### 2.2 Fetch and Display Data in `index.tsx` Let's set up `index.tsx` to fetch the post we added to the database. First, import the necessary modules: ```typescript file=app/routes/index.tsx showLineNumbers // add-start import { PrismaClient } from "../generated/prisma"; import { createServerFn } from "@tanstack/react-start"; // add-end ``` Create an instance of the Prisma Client: ```typescript file=app/routes/index.tsx showLineNumbers // add-start const prisma = new PrismaClient(); // add-end ``` Create a server function using TanStack Start's `createServerFn` to fetch the posts from the database using `.findMany()`: ```typescript file=app/routes/index.tsx showLineNumbers // add-start const getPosts = createServerFn({ method: "GET" }).handler(async () => { return prisma.post.findMany(); }); // add-end ``` TanStack Start allows functions to run on load with loader functions in the `createFileRoute` function. Fetch the posts on load with this code: ```typescript file=app/routes/index.tsx showLineNumbers export const Route = createFileRoute("/")({ component: Home, // add-start loader: () => { return getPosts(); }, // add-end }); ``` Store the response from the loader in the main component using `Route.useLoaderData()`: ```typescript file=app/routes/index.tsx showLineNumbers function Home() { // add-start const posts = Route.useLoaderData(); // add-end return ( <div> <h1>Posts</h1> </div> ); } ``` Map over the posts and display them in a list: ```typescript file=app/routes/index.tsx showLineNumbers function Home() { const posts = Route.useLoaderData(); return ( <div> <h1>Posts</h1> // add-start <ul> {posts.map((post) => ( <li key={post.id}> <h3>{post.title}</h3> <p>{post.content}</p> </li> ))} </ul> // add-end </div> ); } ``` This setup will display the posts on your page, fetched directly from your database. ## Next Steps You've successfully integrated Prisma ORM with TanStack Start, creating a seamless full-stack application. Here are a few suggestions for what you can do next: - Expand your Prisma models to handle more complex data relationships. - Implement additional CRUD operations to enhance your application's functionality. - Explore more features of Prisma and TanStack Start to deepen your understanding. - Check out [Prisma Postgres](https://www.prisma.io/postgres) to see how you can scale your application. ### More Info - [Prisma ORM Documentation](/orm/overview/introduction) - [TanStack Start Documentation](https://tanstack.com/start/latest/docs/framework/react/overview) --- # How to use Prisma ORM with React Router 7 URL: https://www.prisma.io/docs/guides/react-router-7 ## Introduction This guide shows you how to use Prisma ORM with React Router 7, a multi-strategy router that can be as minimal as declarative routing or as full-featured as a fullstack framework. You'll learn how to set up Prisma ORM and Prisma Postgres with React Router and handle migrations. You can find a [deployment-ready example on GitHub](https://github.com/prisma/prisma-examples/blob/latest/orm/react-router-7). ## Prerequisites Before starting this guide, make sure you have: - Node.js 20+ installed - A [Prisma Data Platform](https://console.prisma.io) account ## 1. Set up your project From the directory where you want to create your project, run `create-react-router` to create a new React Router app that we will be using for this guide. ```terminal npx create-react-router@latest my-app ``` You will be prompted if you want to initalize a new git repository and install dependencies with npm. Select yes for both. Now, navigate to the project directory: ```terminal cd my-app ``` ## 2. Set up Prisma ORM ### 2.1 Install Prisma ORM and create your first models First, we need to install a few dependencies. At the root of your project in your terminal, run: ```terminal npm install prisma --save-dev npm install tsx --save-dev ``` Then, run `prisma init --db` to initialize Prisma ORM and a Prisma Postgres database for your project. ```terminal npx prisma init --db --output ../app/generated/prisma ``` :::note You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database like "My React Router Project" ::: This will create a new `prisma` directory in your project, with a `schema.prisma` file inside of it. The `schema.prisma` file is where you will define your database models. The `prisma init` command also creates a `.env` file in your project root, which is used to store your database connection string, and outputs the generated Prisma Client into the `/app/generated/prisma` directory. Next, let's change the generator to use the `prisma-client` provider and add two models to your `schema.prisma` file. A `User` model and a `Post` model. ```prisma file=prisma/schema.prisma generator client { //add-next-line provider = "prisma-client" //delete-next-line provider = "prisma-client-js" output = "../app/generated/prisma" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } //add-start model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) authorId Int author User @relation(fields: [authorId], references: [id]) } //add-end ``` This represents a simple blog with users and posts. Each `Post` can have a `User` as an author and each `User` can have many `Post`s. Now that we have a Prisma Schema and a model, let's migrate our Prisma Postgres database. ### 2.2 Update your database schema :::warning If you're connecting to a database with existing data, use the `prisma db pull` command and then skip to [Set up Prisma Client](#24-set-up-prisma-client). ::: We can apply your new schema to your database using the `prisma migrate dev` command. ```terminal npx prisma migrate dev --name init ``` This creates an initial migration creating the `User` and `Post` tables and applies that migration to your database. Now, let's add some initial data to our database. ### 2.3 Seed your database Prisma ORM has built-in support for seeding your database with initial data. To do this, you can create a new file called `seed.ts` in the `prisma` directory. ```ts file=prisma/seed.ts import { PrismaClient, Prisma } from '../app/generated/prisma' const prisma = new PrismaClient() const userData: Prisma.UserCreateInput[] = [ { name: 'Alice', email: 'alice@prisma.io', posts: { create: [ { title: 'Join the Prisma Discord', content: 'https://pris.ly/discord', published: true, }, { title: 'Prisma on YouTube', content: 'https://pris.ly/youtube', }, ], }, }, { name: 'Bob', email: 'bob@prisma.io', posts: { create: [ { title: 'Follow Prisma on Twitter', content: 'https://www.twitter.com/prisma', published: true, }, ], }, } ] export async function main() { for (const u of userData) { await prisma.user.create({ data: u }) } } main() ``` Now, add the `prisma.seed` configuration to your `package.json` file. ```json file=package.json { "name": "my-app", "private": true, "type": "module", "scripts": { "build": "react-router build", "dev": "react-router dev", "start": "react-router-serve ./build/server/index.js", "typecheck": "react-router typegen && tsc" }, //add-start "prisma": { "seed": "tsx prisma/seed.ts" }, //add-end "dependencies": { "@react-router/node": "^7.3.0", "@react-router/serve": "^7.3.0", "isbot": "^5.1.17", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router": "^7.3.0" }, "devDependencies": { "@react-router/dev": "^7.3.0", "@tailwindcss/vite": "^4.0.0", "@types/node": "^20", "@types/react": "^19.0.1", "@types/react-dom": "^19.0.1", "prisma": "^6.5.0", "react-router-devtools": "^1.1.0", "tailwindcss": "^4.0.0", "tsx": "^4.19.3", "typescript": "^5.7.2", "vite": "^5.4.11", "vite-tsconfig-paths": "^5.1.4" } } ``` Finally, run `prisma db seed` to seed your database with the initial data we defined in the `seed.ts` file. ```terminal npx prisma db seed ``` We now have a database with some initial data! You can check out the data in your database by running `prisma studio`. ```terminal npx prisma studio ``` ### 2.4 Set up Prisma Client Now that we have a database with some initial data, we can set up Prisma Client and connect it to our database. Inside of your `app` directory, create a new `lib` directory and add a `prisma.ts` file to it. ```terminal mkdir -p app/lib && touch app/lib/prisma.ts ``` Now, add the following code to your `app/lib/prisma.ts` file: ```ts file=app/lib/prisma.ts import { PrismaClient } from "../generated/prisma"; declare global { // avoid multiple instances when hot-reloading var prismaClient: PrismaClient; } globalThis.prismaClient ??= new PrismaClient(); const prisma = globalThis.prismaClient; export default prisma; ``` This file creates a Prisma Client and attaches it to the global object so that only one instance of the client is created in your application. This helps resolve issues with hot reloading that can occur when using Prisma ORM in development. We'll use this client in the next section to run your first queries. ## 3. Query your database with Prisma ORM Now that we have an initialized Prisma Client, a connection to our database, and some initial data, we can start querying our data with Prisma ORM. In our example, we'll be making the "home" page of our application display all of our users. Open the `app/routes/home.tsx` file and replace the existing code with the following: ```tsx file=app/routes/home.tsx import type { Route } from "./+types/home"; export function meta({}: Route.MetaArgs) { return [ { title: "New React Router App" }, { name: "description", content: "Welcome to React Router!" }, ]; } export default function Home({ loaderData }: Route.ComponentProps) { return ( <div className="min-h-screen flex flex-col items-center justify-center -mt-16"> <h1 className="text-4xl font-bold mb-8 font-[family-name:var(--font-geist-sans)]"> Superblog </h1> <ol className="list-decimal list-inside font-[family-name:var(--font-geist-sans)]"> <li className="mb-2">Alice</li> <li>Bob</li> </ol> </div> ); } ``` :::note If you see an error on the first line, `import type { Route } from "./+types/home";`, make sure you run `npm run dev` so React Router generates needed types. ::: This gives us a basic page with a title and a list of users. However, the list of users is static. Let's update the page to fetch the users from our database and make it dynamic. ```tsx file=app/routes/home.tsx import type { Route } from "./+types/home"; //add-start import prisma from '~/lib/prisma' //add-end export function meta({}: Route.MetaArgs) { return [ { title: "New React Router App" }, { name: "description", content: "Welcome to React Router!" }, ]; } //add-start export async function loader() { const users = await prisma.user.findMany(); return { users }; } //add-end export default function Home({ loaderData }: Route.ComponentProps) { //add-start const { users } = loaderData; //add-end return ( <div className="min-h-screen flex flex-col items-center justify-center -mt-16"> <h1 className="text-4xl font-bold mb-8 font-[family-name:var(--font-geist-sans)]"> Superblog </h1> <ol className="list-decimal list-inside font-[family-name:var(--font-geist-sans)]"> //add-start {users.map((user) => ( <li key={user.id} className="mb-2"> {user.name} </li> ))} //add-end </ol> </div> ); } ``` We are now importing our client, using [a React Router loader](https://reactrouter.com/start/framework/data-loading#server-data-loading) to query the `User` model for all users, and then displaying them in a list. Now your home page is dynamic and will display the users from your database. ### 3.1 Update your data (optional) If you want to see what happens when data is updated, you could: - update your `User` table via a SQL browser of your choice - change your `seed.ts` file to add more users - change the call to `prisma.user.findMany` to re-order the users, filter the users, or similar. Just reload the page and you'll see the changes. ## 4. Add a new Posts list page We have our home page working, but we should add a new page that displays all of our posts. First, create a new `posts` directory under the `app/routes` directory and add a `home.tsx` file: ```terminal mkdir -p app/routes/posts && touch app/routes/posts/home.tsx ``` Second, add the following code to the `app/routes/posts/home.tsx` file: ```tsx file=app/routes/posts/home.tsx import type { Route } from "./+types/home"; import prisma from "~/lib/prisma"; export default function Home() { return ( <div className="min-h-screen flex flex-col items-center justify-center -mt-16"> <h1 className="text-4xl font-bold mb-8 font-[family-name:var(--font-geist-sans)]"> Posts </h1> <ul className="font-[family-name:var(--font-geist-sans)] max-w-2xl space-y-4"> <li>My first post</li> </ul> </div> ); } ``` Second, update the `app/routes.ts` file so when you visit the `/posts` route, the `posts/home.tsx` page is shown: ```tsx file=app/routes.ts export default [ index("routes/home.tsx"), //add-start route("posts", "routes/posts/home.tsx"), //add-end ] satisfies RouteConfig; ``` Now `localhost:5173/posts` will load, but the content is static. Let's update it to be dynamic, similarly to the home page: ```tsx file=app/routes/posts/home.tsx import type { Route } from "./+types/home"; import prisma from "~/lib/prisma"; //add-start export async function loader() { const posts = await prisma.post.findMany({ include: { author: true, }, }); return { posts }; } //add-end export default function Posts({ loaderData }: Route.ComponentProps) { //add-start const { posts } = loaderData; //add-end return ( <div className="min-h-screen flex flex-col items-center justify-center -mt-16"> <h1 className="text-4xl font-bold mb-8 font-[family-name:var(--font-geist-sans)]"> Posts </h1> <ul className="font-[family-name:var(--font-geist-sans)] max-w-2xl space-y-4"> //delete-start <li>My first post</li> //delete-end //add-start {posts.map((post) => ( <li key={post.id}> <span className="font-semibold">{post.title}</span> <span className="text-sm text-gray-600 ml-2"> by {post.author.name} </span> </li> ))} //add-end </ul> </div> ); } ``` This works similarly to the home page, but instead of displaying users, it displays posts. You can also see that we've used `include` in our Prisma Client query to fetch the author of each post so we can display the author's name. This "list view" is one of the most common patterns in web applications. We're going to add two more pages to our application which you'll also commonly need: a "detail view" and a "create view". ## 5. Add a new Posts detail page To complement the Posts list page, we'll add a Posts detail page. In the `routes/posts` directory, create a new `post.tsx` file. ```terminal touch app/routes/posts/post.tsx ``` This page will display a single post's title, content, and author. Just like our other pages, add the following code to the `app/routes/posts/post.tsx` file: ```tsx file=app/routes/posts/post.tsx import type { Route } from "./+types/post"; import prisma from "~/lib/prisma"; export default function Post({ loaderData }: Route.ComponentProps) { return ( <div className="min-h-screen flex flex-col items-center justify-center -mt-16"> <article className="max-w-2xl space-y-4 font-[family-name:var(--font-geist-sans)]"> <h1 className="text-4xl font-bold mb-8">My first post</h1> <p className="text-gray-600 text-center">by Anonymous</p> <div className="prose prose-gray mt-8"> No content available. </div> </article> </div> ); } ``` And then add a new route for this page: ```tsx file=app/routes.ts export default [ index("routes/home.tsx"), route("posts", "routes/posts/home.tsx"), //add-start route("posts/:postId", "routes/posts/post.tsx"), //add-end ] satisfies RouteConfig; ``` As before, this page is static. Let's update it to be dynamic based on the `params` passed to the page: ```tsx file=app/routes/posts/post.tsx //add-start import { data } from "react-router"; //add-end import type { Route } from "./+types/post"; import prisma from "~/lib/prisma"; //add-start export async function loader({ params }: Route.LoaderArgs) { const { postId } = params; const post = await prisma.post.findUnique({ where: { id: parseInt(postId) }, include: { author: true, }, }); if (!post) { throw data("Post Not Found", { status: 404 }); } return { post }; } //add-end export default function Post({ loaderData }: Route.ComponentProps) { //add-start const { post } = loaderData; //add-end return ( <div className="min-h-screen flex flex-col items-center justify-center -mt-16"> <article className="max-w-2xl space-y-4 font-[family-name:var(--font-geist-sans)]"> //delete-start <h1 className="text-4xl font-bold mb-8">My first post</h1> <p className="text-gray-600 text-center">by Anonymous</p> <div className="prose prose-gray mt-8"> No content available. </div> //delete-end //add-start <h1 className="text-4xl font-bold mb-8">{post.title}</h1> <p className="text-gray-600 text-center">by {post.author.name}</p> <div className="prose prose-gray mt-8"> {post.content || "No content available."} </div> //add-end </article> </div> ); } ``` There's a lot of changes here, so let's break it down: - We're using Prisma Client to fetch the post by its `id`, which we get from the `params` object. - In case the post doesn't exist (maybe it was deleted or maybe you typed a wrong ID), we throw an error to display a 404 page. - We then display the post's title, content, and author. If the post doesn't have content, we display a placeholder message. It's not the prettiest page, but it's a good start. Try it out by navigating to `localhost:5173/posts/1` and `localhost:5173/posts/2`. You can also test the 404 page by navigating to `localhost:5173/posts/999`. ## 6. Add a new Posts create page To round out our application, we'll add a "create" page for posts. This will let you write your own posts and save them to the database. As with the other pages, we'll start with a static page and then update it to be dynamic. ```terminal touch app/routes/posts/new.tsx ``` Now, add the following code to the `app/routes/posts/new.tsx` file: ```tsx file=app/routes/posts/new.tsx import type { Route } from "./+types/new"; import { Form } from "react-router"; export async function action({ request }: Route.ActionArgs) { const formData = await request.formData(); const title = formData.get("title") as string; const content = formData.get("content") as string; } export default function NewPost() { return ( <div className="max-w-2xl mx-auto p-4"> <h1 className="text-2xl font-bold mb-6">Create New Post</h1> <Form method="post" className="space-y-6"> <div> <label htmlFor="title" className="block text-lg mb-2"> Title </label> <input type="text" id="title" name="title" placeholder="Enter your post title" className="w-full px-4 py-2 border rounded-lg" /> </div> <div> <label htmlFor="content" className="block text-lg mb-2"> Content </label> <textarea id="content" name="content" placeholder="Write your post content here..." rows={6} className="w-full px-4 py-2 border rounded-lg" /> </div> <button type="submit" className="w-full bg-blue-500 text-white py-3 rounded-lg hover:bg-blue-600" > Create Post </button> </Form> </div> ); } ``` This form looks good, but it doesn't do anything yet. Let's update the `action` to save the post to the database: ```tsx file=app/routes/posts/new.tsx import type { Route } from "./+types/new"; //add-start import { Form, redirect } from "react-router"; import prisma from "~/lib/prisma"; //add-end export async function action({ request }: Route.ActionArgs) { const formData = await request.formData(); const title = formData.get("title") as string; const content = formData.get("content") as string; //add-start try { await prisma.post.create({ data: { title, content, authorId: 1, }, }); } catch (error) { console.error(error); return Response.json({ error: "Failed to create post" }, { status: 500 }); } return redirect("/posts"); //add-end } export default function NewPost() { return ( <div className="max-w-2xl mx-auto p-4"> <h1 className="text-2xl font-bold mb-6">Create New Post</h1> <Form method="post" className="space-y-6"> <div> <label htmlFor="title" className="block text-lg mb-2"> Title </label> <input type="text" id="title" name="title" placeholder="Enter your post title" className="w-full px-4 py-2 border rounded-lg" /> </div> <div> <label htmlFor="content" className="block text-lg mb-2"> Content </label> <textarea id="content" name="content" placeholder="Write your post content here..." rows={6} className="w-full px-4 py-2 border rounded-lg" /> </div> <button type="submit" className="w-full bg-blue-500 text-white py-3 rounded-lg hover:bg-blue-600" > Create Post </button> </Form> </div> ); } ``` Now, add a new route for this page: ```tsx file=app/routes.ts export default [ index("routes/home.tsx"), route("posts", "routes/posts/home.tsx"), route("posts/:postId", "routes/posts/post.tsx"), //add-start route("posts/new", "routes/posts/new.tsx"), //add-end ] satisfies RouteConfig; ``` This page now has a functional form! When you submit the form, it will create a new post in the database and redirect you to the posts list page. Try it out by navigating to `localhost:5173/posts/new` and submitting the form. ## 7. Next steps Now that you have a working React Router application with Prisma ORM, here are some ways you can expand and improve your application: - Add authentication to protect your routes - Add the ability to edit and delete posts - Add comments to posts - Use [Prisma Studio](/orm/tools/prisma-studio) for visual database management For more information and updates: - [Prisma ORM documentation](/orm) - [Prisma Client API reference](/orm/prisma-client) - [React Router documentation](https://reactrouter.com/home) - Join our [Discord community](https://pris.ly/discord) - Follow us on [Twitter](https://twitter.com/prisma) and [YouTube](https://youtube.com/prismadata) --- # How to use Prisma ORM with SolidStart URL: https://www.prisma.io/docs/guides/solid-start ## Introduction Prisma ORM streamlines database access with type-safe queries and a smooth developer experience. SolidStart, a modern framework for building reactive web apps with SolidJS, pairs well with Prisma and Postgres to create a clean and scalable full-stack architecture. In this guide, you'll learn how to integrate Prisma ORM with a Prisma Postgres database in a SolidStart project from scratch. You can find a complete example of this guide on [GitHub](https://github.com/prisma/prisma-examples/tree/latest/orm/solid-start). --- ## Prerequisites Before getting started, make sure you have the following installed: - **Node.js 18+** installed --- ## Step 1: Set Up a SolidStart Project Begin by creating a new SolidStart app. In your terminal, run: ```terminal npm init solid@latest ``` :::info Use the following options when prompted: - **Project name:** `my-solid-prisma-app` *(or any name you prefer)* - **Is this a SolidStart project:** `yes` - **Template:** `bare` - **Use TypeScript:** `yes` ::: Next, navigate into your new project, install dependencies, and start the development server: ```terminal cd my-solid-prisma-app npm install npm run dev ``` Once the dev server is running, open `http://localhost:3000` in your browser. You should see the SolidStart welcome screen. Let's clean up the default UI by editing the `app.tsx` file and replacing the header: ```typescript file=src/app.tsx //delete-next-line import { createSignal } from "solid-js"; import "./app.css"; export default function App() { //delete-next-line const [count, setCount] = createSignal(0); return ( <main> //add-next-line <h1>SolidStart + Prisma</h1> //delete-next-line <h1>Hello world!</h1> //delete-start <button class="increment" onClick={() => setCount(count() + 1)} type="button"> Clicks: {count()} </button> <p> Visit{" "} <a href="https://start.solidjs.com" target="_blank"> start.solidjs.com </a>{" "} to learn how to build SolidStart apps. </p> //delete-end </main> ); } ``` Your `app.tsx` file should now look like this: ```typescript file=src/app.tsx import "./app.css"; export default function App() { return ( <main> <h1>SolidStart + Prisma</h1> </main> ); } ``` --- ## Step 2: Install and Initialize Prisma To get started with Prisma, you'll need to install a few dependencies: ```terminal npm install prisma @prisma/client --save-dev npm install tsx --save-dev npm install @prisma/extension-accelerate ``` :::info If you're not using a Prisma Postgres database, you can skip `@prisma/extension-accelerate`. ::: Once installed, initialize Prisma in your project: ```terminal npx prisma init --db --output ../src/generated/prisma ``` This will create: - A `prisma/` directory with a `schema.prisma` file - A `.env` file with a `DATABASE_URL` already set --- ### Step 2.1: Define Your Prisma Schema Open the `prisma/schema.prisma` file and add the following models and change the generator to use the `prisma-client` provider: ```prisma file=prisma/schema.prisma generator client { //add-next-line provider = "prisma-client" //delete-next-line provider = "prisma-client-js" output = "../src/generated/prisma" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } //add-start model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) authorId Int author User @relation(fields: [authorId], references: [id]) } //add-end ``` This creates two models: `User` and `Post`, with a one-to-many relationship between them. Now, run the following command to create the database tables and generate the Prisma Client: ```terminal npx prisma migrate dev --name init ``` --- ### Step 2.2: Seed the Database Let's add some seed data to populate the database with sample users and posts. Create a new file called `seed.ts` in the `prisma/` directory: ```typescript file=prisma/seed.ts import { PrismaClient, Prisma } from "../src/generated/prisma"; const prisma = new PrismaClient(); const userData: Prisma.UserCreateInput[] = [ { name: "Alice", email: "alice@prisma.io", posts: { create: [ { title: "Join the Prisma Discord", content: "https://pris.ly/discord", published: true, }, { title: "Prisma on YouTube", content: "https://pris.ly/youtube", }, ], }, }, { name: "Bob", email: "bob@prisma.io", posts: { create: [ { title: "Follow Prisma on Twitter", content: "https://www.twitter.com/prisma", published: true, }, ], }, }, ]; export async function main() { for (const u of userData) { await prisma.user.create({ data: u }); } } main(); ``` Now, tell Prisma how to run this script by updating your `package.json`: ```json file=package.json "prisma": { "seed": "tsx prisma/seed.ts" } ``` Run the seed script: ```terminal npx prisma db seed ``` And open Prisma Studio to inspect your data: ```terminal npx prisma studio ``` --- ## Step 3: Use Prisma Client in Your Application ### Step 3.1: Create a Prisma Client At the root of your project, create a new `lib` folder and a `prisma.ts` file inside it: ```terminal mkdir -p lib && touch lib/prisma.ts ``` Add the following code to create a Prisma Client instance: ```typescript file=lib/prisma.ts import { PrismaClient } from "../src/generated/prisma"; import { withAccelerate } from "@prisma/extension-accelerate"; const prisma = new PrismaClient().$extends(withAccelerate()); export default prisma; ``` :::info If you're not using Prisma Postgres, remove `.$extends(withAccelerate())`. ::: --- ### Step 3.2: Create an API Route Now, let's fetch data from the database using an API route. Create a new file at `src/routes/api/users.ts`: ```typescript file=src/routes/api/users.ts import prisma from "../../lib/prisma"; export async function GET() { const users = await prisma.user.findMany({ include: { posts: true, }, }); return new Response(JSON.stringify(users), { headers: { "Content-Type": "application/json" }, }); } ``` --- ## Step 4: Fetch Data in Your Component In your `app.tsx` file, use `createResource` to fetch data from your new API route: ```typescript file=src/app.tsx import "./app.css"; //add-start import { createResource } from "solid-js"; import { User, Post } from "@prisma/client"; type UserWithPosts = User & { posts: Post[]; }; const fetchUsers = async () => { const res = await fetch("http://localhost:3000/api/users"); return res.json(); }; //add-end export default function App() { //add-next-line const [users, { mutate, refetch }] = createResource<UserWithPosts[]>(fetchUsers); return ( <main> <h1>SolidStart + Prisma</h1> </main> ); } ``` :::info `createResource` is a SolidJS hook for managing async data. It tracks loading and error states automatically. [Learn more](https://docs.solidjs.com/reference/basic-reactivity/create-resource#createresource). ::: --- ## Step 5: Display the Data To show the users and their posts, use SolidJS's `<For>` component: ```typescript file=src/app.tsx import "./app.css"; //add-next-line import { createResource, For } from "solid-js"; import { User, Post } from "@prisma/client"; type UserWithPosts = User & { posts: Post[]; }; const fetchUsers = async () => { const res = await fetch("http://localhost:3000/api/users"); return res.json(); }; export default function App() { const [users, { mutate, refetch }] = createResource<UserWithPosts[]>(fetchUsers); return ( <main> <h1>SolidJS + Prisma</h1> //add-start <For each={users() ?? []}> {(user) => ( <div> <h3>{user.name}</h3> <For each={user.posts}>{(post) => <p>{post.title}</p>}</For> </div> )} </For> //add-end </main> ); } ``` :::info `<For>` loops through an array reactively. Think of it like `.map()` in React. [Learn more](https://docs.solidjs.com/reference/components/for) ::: --- ## Step 6: Add Loading and Error States Use SolidJS's `<Show>` component to handle loading and error conditions: ```typescript file=src/app.tsx import "./app.css"; import { createResource, For, Show } from "solid-js"; import { User, Post } from "@prisma/client"; type UserWithPosts = User & { posts: Post[]; }; const fetchUsers = async () => { const res = await fetch("http://localhost:3000/api/users"); return res.json(); }; export default function App() { const [users, { mutate, refetch }] = createResource<UserWithPosts[]>(fetchUsers); return ( <main> <h1>SolidJS + Prisma</h1> //add-start <Show when={!users.loading} fallback={<p>Loading...</p>}> <Show when={!users.error} fallback={<p>Error loading data</p>}> //add-end <For each={users()}> {(user) => ( <div> <h3>{user.name}</h3> <For each={user.posts}>{(post) => <p>{post.title}</p>}</For> </div> )} </For> //add-start </Show> </Show> //add-end </main> ); } ``` :::info `<Show>` conditionally renders content. It's similar to an `if` statement. [Learn more](https://docs.solidjs.com/reference/components/show) ::: --- ## Next Steps Now that you have a working SolidStart app connected to a Prisma Postgres database, you can: - Extend your Prisma schema with more models and relationships - Add create/update/delete routes and forms - Explore authentication, validation, and optimistic updates --- ## More Info - [Prisma ORM Docs](/orm/overview/introduction) - [SolidStart Documentation](https://start.solidjs.com/) --- # How to set up Datadog tracing with Prisma ORM URL: https://www.prisma.io/docs/guides/data-dog ## Introduction In this guide, you'll learn how to set up Datadog tracing for a new Prisma project. By combining the `@prisma/instrumentation` package with Prisma Client extensions, you can capture detailed spans for every database query. These spans are enriched with query metadata and sent to Datadog [using `dd-trace`](https://www.npmjs.com/package/dd-trace), Datadog's official APM library for Node.js, enabling you to monitor, analyze, and gain visibility into your application's database activity. ### What are spans and tracing? - **Spans** are the individual operations or units of work within a distributed system or complex application. Each database query, service call, or external request is represented by a span. - **Tracing** ties these spans together to form a complete, end-to-end picture of a request’s lifecycle. With tracing, you can visualize bottlenecks, identify problematic queries, and pinpoint where errors occur from your queries. ### Why use Datadog with Prisma ORM? [Datadog](https://www.datadoghq.com/) provides application performance monitoring (APM), metrics, logs, and dashboards to help you observe and debug production systems. While Prisma ORM abstracts away SQL and boosts developer productivity, it can obscure query performance without proper instrumentation. By integrating Datadog with Prisma using `@prisma/instrumentation` and [`dd-trace`](https://www.npmjs.com/package/dd-trace), you can automatically capture spans for every database query. This enables you to: - Measure latency per query. - Inspect query arguments and raw SQL. - Trace Prisma operations in the context of application-level requests. - Identify bottlenecks related to database access. This integration provides runtime visibility into Prisma queries with minimal effort, helping you catch slow queries and errors in real time. ## Prerequisites Before you begin, ensure you have the following: - **Node.js** installed (v18+ recommended). - A local or hosted **PostgreSQL** database. - A **Datadog** account. If you do not have one, [sign up here](https://www.datadoghq.com/). - The **Datadog Agent** installed and running on your machine or server where this application will run. You can follow the [Datadog Agent installation docs](https://docs.datadoghq.com/agent/) to set it up. ## 1. Create a new project We will start by creating a new Node.js project to demonstrate tracing with Datadog and Prisma ORM. This will be a minimal, standalone setup focused on running and tracing Prisma queries, to understand the instrumentation flow in isolation. If you're integrating tracing into an existing Prisma project, you can skip this step and directly follow from [the setup tracing section](#4-set-up-datadog-tracing). Just make sure you apply the changes in your project's equivalent folder structure. ```terminal mkdir prisma-datadog-tracing cd prisma-datadog-tracing npm init -y ``` In this setup, you'll: - Define a Prisma schema with basic models. - Connect to a Postgres database (Prisma Postgres or your own). - Configure Datadog tracing for all queries using `@prisma/instrumentation` and `dd-trace`. - Run a sample script that executes Prisma operations and sends spans to Datadog. ## 2. Set up Prisma ORM In this section, you will install Prisma, create your schema, and generate the Prisma Client. This prepares your application to run database queries—queries that you will trace with Datadog. ### 2.1. Install and initialize Prisma ORM Run the following commands to install Prisma and a minimal TypeScript runner: ```terminal npm install -D prisma tsx ``` Then initialize Prisma: :::note You can use the `--db` flag to create a [new Prisma Postgres](/postgres) instance when initializing Prisma in your project. ::: <TabbedContent code> <TabItem value="Prisma Postgres (recommended)"> <br /> ```terminal npx prisma init --db --output ../src/generated/prisma ``` :::note You will be prompted to name your database and select the closest region. For clarity, choose a memorable name (e.g., `My Datadog Project`). ::: </TabItem> <TabItem value="Your own database"> ```terminal npx prisma init --output ../src/generated/prisma ``` </TabItem> </TabbedContent> This command does the following: - Creates a `prisma` directory with a `schema.prisma` file. - Generates the Prisma Client in the `/src/generated/prisma` directory (as specified in the `--output` flag). - Creates a `.env` file at the project root with your database connection string (`DATABASE_URL`). If you did not use the `--db` flag, replace the placeholder database URL in the `.env` file: <TabbedContent code> <TabItem value="Prisma Postgres"> ```bash file=.env DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/?api_key=..." ``` </TabItem> <TabItem value="Your own database"> ```bash file=.env # Placeholder url you have to replace DATABASE_URL="postgresql://janedoe:mypassword@localhost:5432/mydb?schema=sample" ``` </TabItem> </TabbedContent> If you're using Prisma Postgres, also install: ```terminal npm i @prisma/extension-accelerate ``` This extension enables you to [cache your Prisma queries](/postgres/caching). ### 2.2. Define models Now, open `prisma/schema.prisma` and update your generator block and models. Replace the `generator` block with the following, and add a `User` and a `Post` model: ```prisma file=prisma/schema.prisma generator client { provider = "prisma-client-js" output = "../src/generated/prisma" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } //add-start model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) authorId Int author User @relation(fields: [authorId], references: [id]) } //add-end ``` ### 2.3. Generate the Prisma Client and run migrations Generate the Prisma Client and apply your schema to your database: ```terminal npx prisma generate npx prisma migrate dev --name "init" ``` This creates the tables according to your schema in the Postgres database and generates a client for you to interact with the database. ## 3. Install required dependencies for tracing In addition to Prisma, you will need the following packages for Datadog tracing: ```terminal npm install @prisma/instrumentation \ dd-trace ``` Also ensure you have development dependencies for TypeScript: ```terminal npm install -D typescript ``` Here's a quick overview: - **`@prisma/instrumentation`**: Instruments Prisma queries so they appear as spans in your tracer. - **`dd-trace`**: Official Node.js tracing library from Datadog. ## 4. Set up Datadog tracing Create a `tracer.ts` file in the `src` folder to instantiate your tracing logic: ```terminal touch src/tracer.ts ``` ### 4.1. Configure the tracer Open `src/tracer.ts` and add the following code: ```ts file=src/tracer.ts import Tracer from "dd-trace"; import { PrismaInstrumentation, registerInstrumentations, } from "@prisma/instrumentation"; const tracer = Tracer.init({ apmTracingEnabled: true, service: "prisma-datadog-tracing", version: "1.0.0", profiling: true }); const provider = new tracer.TracerProvider(); // Register the provider globally provider.register(); registerInstrumentations({ instrumentations: [ new PrismaInstrumentation({ enabled: true, }), ], tracerProvider: provider, }); export { tracer }; ``` :::note If you encounter a linting error on the line `traceProvider: provider` due to incompatible types, it's likely caused by a version mismatch in the `@opentelemetry/api` package. To resolve this, add the following override to your package.json: ```json //add-start "overrides": { "@opentelemetry/api": "1.8.0" } //add-end ``` This is necessary because [`dd-trace` does not yet support version `1.9.0` or above of `@opentelemetry/api`](https://github.com/DataDog/dd-trace-js#datadog-with-opentelemetery). After updating the `package.json`, reinstall your dependencies: ```terminal npm i ``` This should resolve the linting error. ::: #### Explanation - **`Tracer.init`** configures `dd-trace` with a `service` name. This name appears in Datadog under your `APM` > `Services` list. - **`@prisma/instrumentation`** automatically logs each Prisma query as a Datadog span. - The `middleware: true` option ensures that each query is intercepted for instrumentation. ## 5. Instantiate Prisma and run queries ### 5.1. Create the Prisma Client instance Create a `src/client.ts` to hold your Prisma Client instantiation: <TabbedContent code> <TabItem value="Prisma Postgres (recommended)"> ```ts file=src/client.ts import { tracer } from "./tracer"; import { withAccelerate } from "@prisma/extension-accelerate"; import { PrismaClient } from "./generated/prisma"; const prisma = new PrismaClient({ log: [{ emit: "event", level: "query" }], }) .$on("query", (e) => { const span = tracer.startSpan(`prisma_raw_query`, { childOf: tracer.scope().active() || undefined, tags: { "prisma.rawquery": e.query, }, }); span.finish(); }) .$extends({ query: { async $allOperations({ operation, model, args, query }) { const span = tracer.startSpan( `prisma_query_${model?.toLowerCase()}_${operation}`, { tags: { "prisma.operation": operation, "prisma.model": model, "prisma.args": JSON.stringify(args), "prisma.rawQuery": query, }, childOf: tracer.scope().active() || undefined, } ); try { const result = await query(args); span.finish(); return result; } catch (error) { span.setTag("error", error); span.finish(); throw error; } }, }, }) .$extends(withAccelerate()); export { prisma }; ``` </TabItem> <TabItem value="Your own database"> ```ts file=src/client.ts import { tracer } from "./tracer"; import { withAccelerate } from "@prisma/extension-accelerate"; import { PrismaClient } from "./generated/prisma"; const prisma = new PrismaClient({ log: [{ emit: "event", level: "query" }], }) .$on("query", (e) => { const span = tracer.startSpan(`prisma_raw_query`, { childOf: tracer.scope().active() || undefined, tags: { "prisma.rawquery": e.query, }, }); span.finish(); }) .$extends({ query: { async $allOperations({ operation, model, args, query }) { const span = tracer.startSpan( `prisma_query_${model?.toLowerCase()}_${operation}`, { tags: { "prisma.operation": operation, "prisma.model": model, "prisma.args": JSON.stringify(args), "prisma.rawQuery": query, }, childOf: tracer.scope().active() || undefined, } ); try { const result = await query(args); span.finish(); return result; } catch (error) { span.setTag("error", error); span.finish(); throw error; } }, }, }); export { prisma }; ``` </TabItem> </TabbedContent> The setup above gives you more control over how queries are traced: - Tracing is initialized as early as possible by importing the `tracer` before creating the Prisma Client. - The `$on("query")` hook captures raw SQL queries and sends them as standalone spans. - The `$allOperations` extension wraps all Prisma operations in custom spans, allowing you to tag them with metadata like the model, operation type, and arguments. Unlike the `@prisma/instrumentation` package, which offers automatic tracing out of the box, this manual setup gives you full control over how each span is structured and tagged. It's helpful when you need custom span names, additional metadata, a simpler setup, or when working around limitations or compatibility issues in the OpenTelemetry ecosystem. It also allows you to adapt tracing behavior based on query context, which can be especially useful in complex applications. ### 5.2. Add a script that performs queries Create a `src/index.ts` file and add code to perform queries to your database and send traces to Datadog: ```typescript file=src/index.ts import { prisma } from "./client"; async function main() { const user1Email = `alice${Date.now()}@prisma.io`; const user2Email = `bob${Date.now()}@prisma.io`; let alice, bob; // 1. Create users concurrently try { [alice, bob] = await Promise.all([ prisma.user.create({ data: { email: user1Email, name: "Alice", posts: { create: { title: "Join the Prisma community on Discord", content: "https://pris.ly/discord", published: true, }, }, }, include: { posts: true }, }), prisma.user.create({ data: { email: user2Email, name: "Bob", posts: { create: [ { title: "Check out Prisma on YouTube", content: "https://pris.ly/youtube", published: true, }, { title: "Follow Prisma on Twitter", content: "https://twitter.com/prisma/", published: false, }, ], }, }, include: { posts: true }, }), ]); console.log( `✅ Created users: ${alice.name} (${alice.posts.length} post) and ${bob.name} (${bob.posts.length} posts)` ); } catch (err) { console.error("❌ Error creating users:", err); return; } // 2. Fetch all published posts try { const publishedPosts = await prisma.post.findMany({ where: { published: true }, }); console.log(`✅ Retrieved ${publishedPosts.length} published post(s).`); } catch (err) { console.error("❌ Error fetching published posts:", err); } // 3. Create & publish a post for Alice let post; try { post = await prisma.post.create({ data: { title: "Join the Prisma Discord community", content: "https://pris.ly/discord", published: false, author: { connect: { email: user1Email } }, }, }); console.log(`✅ Created draft post for Alice (ID: ${post.id})`); } catch (err) { console.error("❌ Error creating draft post for Alice:", err); return; } try { post = await prisma.post.update({ where: { id: post.id }, data: { published: true }, }); console.log("✅ Published Alice’s post:", post); } catch (err) { console.error("❌ Error publishing Alice's post:", err); } // 4. Fetch all posts by Alice try { const alicePosts = await prisma.post.findMany({ where: { author: { email: user1Email } }, }); console.log( `✅ Retrieved ${alicePosts.length} post(s) by Alice.`, alicePosts ); } catch (err) { console.error("❌ Error fetching Alice's posts:", err); } } // Entrypoint main() .catch((err) => { console.error("❌ Unexpected error:", err); process.exit(1); }) .finally(async () => { await prisma.$disconnect(); console.log("🔌 Disconnected from database."); }); ``` ## 6. Run your queries and see the traces Run the queries: ```terminal npx tsx src/index.ts ``` This executes your script, which: - Registers the Datadog tracer. - Performs multiple Prisma queries. - Logs the result of each operation. Then, confirm the traces in Datadog: - Open your [Datadog APM page](https://docs.datadoghq.com/tracing/). - Navigate to **APM > Traces > Explorer** in the side panel. - Explore the list of traces and spans, each representing a Prisma query (e.g. `prisma:query`). :::info Depending on your Datadog setup, it may take a minute or two for new data to appear. Refresh or wait briefly if you do not see traces right away. ::: ## Next steps You have successfully: - Created a Prisma ORM project with [Prisma Postgres](/postgres). - Set up Datadog tracing using `@prisma/instrumentation` and `dd-trace`. - Verified that database operations show up as spans in Datadog. To improve your observability further: - Add more instrumentation for your HTTP server or other services (e.g., Express, Fastify). - [Create Dashboards to view](https://docs.datadoghq.com/dashboards/) key metrics from your data. For additional guidance, check out: - [Datadog APM documentation](https://docs.datadoghq.com/tracing/). - [Prisma tracing docs](/orm/prisma-client/observability-and-logging/opentelemetry-tracing). --- # How to use Prisma ORM with SvelteKit URL: https://www.prisma.io/docs/guides/sveltekit ## Introduction Prisma ORM simplifies database access with type-safe queries, and when paired with [SvelteKit](https://svelte.dev/docs/kit), it creates a robust and scalable full-stack architecture. In this guide, you'll learn to integrate Prisma ORM with a Prisma Postgres database in a SvelteKit project from scratch. You can find a complete example of this guide on [GitHub](https://github.com/prisma/prisma-examples/tree/latest/orm/sveltekit). ## Prerequisites - [Node.js 18+](https://nodejs.org) - [Svelte VSCode extension](https://marketplace.visualstudio.com/items?itemName=svelte.svelte-vscode) (Recommended by Svelte) ## 1. Set up your project You'll be using [Svelte CLI](https://github.com/sveltejs/cli) instead of `npx create svelte@latest`. This CLI provides a more interactive setup and built-in support for popular tooling like ESLint and Prettier Create a new Svelte project: ```terminal npx sv create sveltekit-prisma ``` It will prompt you to customize your setup. Here are the options you'll choose: :::info - *Which template would you like?* `SvelteKit minimal` - *Add type checking with TypeScript?* `Yes, using TypeScript syntax` - *What would you like to add to your project?* `prettier, eslint` - *Which package manager do you want to install dependencies with?* `npm` ::: Once the setup completes, navigate into your project and start the development server: ```terminal cd sveltekit-prisma npm install npm run dev ``` That's it! Svelte makes it a very simple process to get up and running. At this point, your project is ready to integrate Prisma and connect to a Prisma Postgres database. ## 2. Install and Configure Prisma ### 2.1. Install dependencies To get started with Prisma, you'll need to install a few dependencies: ```terminal npm install prisma --save-dev npm install tsx --save-dev npm install @prisma/extension-accelerate ``` :::info If you're not using a Prisma Postgres database, you can skip installing `@prisma/extension-accelerate`. ::: Once installed, initialize Prisma in your project: ```terminal npx prisma init --db --output ../src/generated/prisma ``` :::info If you're not using a Prisma Postgres database, you can skip the `--db` flag. You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database like "My SvelteKit Project" ::: This will create: - A `prisma/` directory with a `schema.prisma` file - A `.env` file with a `DATABASE_URL` already set *(if you're using Prisma Postgres)* ### 2.2. Define your Prisma Schema In the `prisma/schema.prisma` file, add the following models and change the generator to use the `prisma-client` provider: ```prisma file=prisma/schema.prisma showLineNumbers generator client { //add-next-line provider = "prisma-client" //delete-next-line provider = "prisma-client-js" output = "../generated/prisma" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } //add-start model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) authorId Int author User @relation(fields: [authorId], references: [id]) } //add-end ``` This creates two models: `User` and `Post`, with a one-to-many relationship between them. ### 2.3. Configure the Prisma Client generator Now, run the following command to create the database tables and generate the Prisma Client: ```terminal npx prisma migrate dev --name init ``` ### 2.4. Seed the database Let's add some seed data to populate the database with sample users and posts. Create a new file called `seed.ts` in the `prisma/` directory: ```typescript file=prisma/seed.ts showLineNumbers //add-next-line import { PrismaClient, Prisma } from "../src/generated/prisma"; //add-next-line const prisma = new PrismaClient(); //add-start const userData: Prisma.UserCreateInput[] = [ { name: "Alice", email: "alice@prisma.io", posts: { create: [ { title: "Join the Prisma Discord", content: "https://pris.ly/discord", published: true, }, { title: "Prisma on YouTube", content: "https://pris.ly/youtube", }, ], }, }, { name: "Bob", email: "bob@prisma.io", posts: { create: [ { title: "Follow Prisma on Twitter", content: "https://www.twitter.com/prisma", published: true, }, ], }, }, ]; //add-end //add-start export async function main() { for (const u of userData) { await prisma.user.create({ data: u }); } } //add-end //add-next-line main(); ``` Now, tell Prisma how to run this script by updating your `package.json`: ```json file=package.json "prisma": { "seed": "tsx prisma/seed.ts" } ``` Run the seed script: ```terminal npx prisma db seed ``` And open Prisma Studio to inspect your data: ```terminal npx prisma studio ``` ## 3. Integrate Prisma into SvelteKit ### 3.1. Create a Prisma Client Inside your `/src/lib` directory, rename `index.ts` to `prisma.ts`. This file will be used to create and export your Prisma Client instance. :::tip Files in `src/lib` can be accessed from anywhere using the `$lib` alias. ::: Set up the Prisma client like this: <TabbedContent code> <TabItem value="Prisma Postgres (recommended)"> ```tsx file=src/lib/prisma.ts showLineNumbers import { PrismaClient } from "../generated/prisma"; import { withAccelerate } from "@prisma/extension-accelerate"; const prisma = new PrismaClient().$extends(withAccelerate()); export default prisma; ``` </TabItem> <TabItem value="Other databases"> ```tsx file=src/lib/prisma.ts showLineNumbers import { PrismaClient } from "../generated/prisma"; const prisma = new PrismaClient(); export default prisma; ``` </TabItem> </TabbedContent> :::warning We recommend using a connection pooler (like [Prisma Accelerate](https://www.prisma.io/accelerate)) to manage database connections efficiently. If you choose not to use one, **avoid** instantiating `PrismaClient` globally in long-lived environments. Instead, create and dispose of the client per request to prevent exhausting your database connections. ::: ### 3.2. Create a server route To fetch data from the database on the server side, create a `+page.server.ts` file in your routes directory. This file should export a `load` function, which runs on the server before your page renders. Start with a basic `load` function: ```typescript file=src/routes/+page.server.ts showLineNumbers //add-start export async function load() {} //add-end ``` Use the `findMany()` method to get a list of users with their basic fields. Update your `+page.server.ts` file like this: ```typescript file=src/routes/+page.server.ts showLineNumbers //add-next-line import prisma from '$lib/prisma'; export async function load() { //add-start const users = await prisma.user.findMany({}); return { users }; //add-end } ``` At this point, you're only getting data directly on the `User` model — no relations like posts are included yet. To also fetch each user's posts, we can expand the query using the `include` option. This tells Prisma to join the related `Posts` table in the result. Update your `findMany()` call like this: ```typescript file=src/routes/+page.server.ts showLineNumbers import prisma from '$lib/prisma'; export async function load() { const users = await prisma.user.findMany({ //add-start include: { posts: true } //add-end }); return { users }; } ``` Now, every user in the result will also include a `posts` array. ### 3.3. Populate the page In `src/routes/+page.svelte`, strip the file down to the basics and add a `<script>` fragment: ```html file=src/routes/+page.svelte showLineNumbers //add-start <script lang="ts"> </script> //add-end //add-next-line <h1>SvelteKit + Prisma</h1> //delete-start <h1>Welcome to SvelteKit</h1> <p>Visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to read the documentation</p> //delete-end ``` We need to grab the data exported from `+page.server.ts`: ```html file=src/routes/+page.svelte showLineNumbers <script lang="ts"> //add-next-line let { data } = $props(); </script> <h1>SvelteKit + Prisma</h1> ``` Now that we have the data, let's map through the users and their posts with Svelte's [`each`](https://svelte.dev/docs/svelte/each) block: ```html file=src/routes/+page.svelte showLineNumbers <script lang="ts"> let { data } = $props(); </script> <h1>SvelteKit + Prisma</h1> //add-start {#each data.users as user} <h2>{user.name}</h2> {#each user.posts as post} <ul> <li><a href={post.content}>{post.title}</a></li> </ul> {/each} {/each} //add-end ``` You're done! You've just created a SvelteKit app with Prisma ORM. Below are some next steps to explore, as well as some more resources to help you get started expanding your project. ## Next Steps Now that you have a working SvelteKit app connected to a Prisma Postgres database, you can: - Extend your Prisma schema with more models and relationships - Add create/update/delete routes and forms - Explore authentication and validation - Enable query caching with [Prisma Postgres](/postgres/caching) for better performance ### More Info - [Prisma Documentation](/orm/overview/introduction) - [SvelteKit Documentation](https://svelte.dev/docs/kit) --- # How to write guides for Prisma ORM URL: https://www.prisma.io/docs/guides/making-guides ## Introduction This guide shows you how to write guides for Prisma ORM documentation. It covers the required structure, formatting, and style conventions to ensure consistency across all guides. You'll learn about frontmatter requirements, section organization, and writing style. ## Prerequisites Before writing a guide, make sure you have: - A clear understanding of the topic you're writing about - Access to the Prisma documentation repository - Familiarity with Markdown and MDX - Knowledge of the target audience for your guide ## Guide structure ### Required frontmatter Every guide must include the following frontmatter at the top of the file: ```mdx --- title: 'How to [do something] with Prisma ORM' metaTitle: 'How to [do something] with Prisma ORM' description: 'Learn how to [do something] with Prisma ORM' sidebar_label: '[Concise Label]' image: '/img/guides/[guide-name]-cover.png' community_section: true --- ``` - `title`: Should be action-oriented and start with "How to" - `metaTitle`: Usually matches the title, used for SEO - `description`: A one-sentence summary starting with "Learn how to", used for SEO - `sidebar_label`: A concise label for the sidebar navigation - `image`: A unique header image for social media sharing (coordinate with the design team) All frontmatter fields should be in sentence case, except for `image`. ### Required sections 1. **Introduction** - Brief overview of what the guide covers - What the reader will learn/accomplish - Link to any example repositories or related resources 2. **Prerequisites** - Required software/tools with version numbers - Required knowledge/experience - Any necessary accounts or access 3. **Main content sections** - Numbered steps for procedural guides (e.g., "1. Set up the project") - Clear hierarchy with H2 (`##`) for main sections - H3 (`###`) for subsections - Each step should build on previous steps 4. **Next steps** - What to do after completing the guide - Related guides or documentation - Links to additional resources - Community resources (e.g., Discord) ## Writing style and voice ### General principles - Write in a clear, conversational tone - Use active voice and present tense - Address the reader directly using "you" - Use first person plural ("we") when guiding the reader through steps - Avoid jargon and explain technical terms - Be concise but thorough ### Code examples - Include complete, runnable code examples - Use syntax highlighting with language specification - Include file paths in code block metadata - Use comments to explain complex parts - Show both the problem and solution when applicable Example: ```typescript file=src/index.ts // Import required dependencies import { PrismaClient } from '@prisma/client' // Initialize Prisma Client const prisma = new PrismaClient() ``` ### Formatting conventions - Use backticks for: - File names: \`schema.prisma\` - Directory names: \`prisma/\` - Code elements: \`PrismaClient\` - Commands: \`npx prisma generate\` - Use [admonitions](https://docusaurus.io/docs/markdown-features/admonitions) for important notes, warnings, tips, etc.: ```mdx :::note Important information goes here ::: ``` - Use proper heading hierarchy (never skip levels) - Include line numbers in longer code blocks - Use tabbed content for alternative approaches ## Examples from existing guides ### Migration guide format Migration guides follow a specific pattern, as seen in guides like [Migrate from Sequelize](/guides/migrate-from-sequelize) and [Migrate from Mongoose](/guides/migrate-from-mongoose): 1. Clear introduction explaining the migration path 2. Prerequisites specific to both ORMs 3. Step-by-step migration process 4. Code comparison between ORMs 5. Practical examples of common operations ### Integration guide format Integration guides, like [Using Prisma ORM with Cloudflare D1](/guides/cloudflare-d1), focus on: 1. Setup and configuration 2. Platform-specific considerations 3. Step-by-step implementation 4. Deployment instructions 5. Platform-specific best practices ## Best practices 1. **Keep it focused** - Each guide should cover one main topic - Break complex topics into multiple guides - Link to related guides instead of duplicating content 2. **Show don't tell** - Include practical, real-world examples - Provide complete, working code samples - Explain why certain approaches are recommended 3. **Consider the context** - Explain prerequisites clearly - Don't assume prior knowledge - Link to foundational concepts within or outside of our docs when needed 4. **Maintain consistency** - Follow the established guide structure - Use consistent terminology - Match the style of existing guides 5. **Think about maintenance** - Use version numbers where appropriate - Avoid time-sensitive references - Consider future updates when structuring content ## Template This is a template for a guide. It is to standarize the format of the guide, the prisma integration, and make it easier to write a guide. Before you submit a PR, run through the checklist and make sure to read all Dev Note's and remove them. To get the guide into the sidebar, you need to add the following to the `sidebars.ts` file: ```typescript file=sidebars.ts { type: "category", label: "Framework Guides", collapsed: false, collapsible: false, items: [ "guides/turborepo", "guides/nextjs", "guides/nuxt", "guides/tanstack-start", "guides/react-router-7", "guides/solid-start", "guides/sveltekit", //add-next-line "guides/__________", ].sort(), }, ``` Copy and paste the template into a new `.mdx` file: ````markdown --- title: 'How to use Prisma ORM with __________' metaTitle: 'How to use Prisma ORM and Prisma Postgres with __________' description: 'Learn how to use Prisma ORM in a __________ app' sidebar_label: '__________ with Prisma' image: '/img/guides/prisma-__________-cover.png' completion_time: '15 min' community_section: true --- :::warning DEVELOPER CHECKLIST - Remove upon completion - [ ] `CTRL or CMD + F` to find 10 `_`'s and replace them with the framework name. - [ ] Provide a brief overview of the guide's purpose and the benefits of integrating Prisma ORM with the specified framework. - [ ] Link to the official documentation of the framework upon its first mention in the Introduction section. - [ ] List all necessary or recommended prerequisites, including specific software versions and any required accounts or services. - [ ] Name project *<u>framework</u>*-prisma (ie. *<u>sveltekit</u>*-prisma) - [ ] Project creation options should be detailed in an info admonition in this format: ```markdown markdown - *Which package manager would you like to use?* `npm` ``` - [ ] Ensure the appropriate admonitions (note, warning, tip) are used for important information. - [ ] Include links to related guides and resources throughout the content. - [ ] Instead of using `we, we'll, ours, etc.` use `you, you'll, yours, etc.` - [ ] All lines ending before a code block should end with a colon (This one -> `:`) ::: ## Introduction Prisma ORM streamlines database access with type-safe queries, and when paired with [__________](https://example.com/), it creates a... :::warning ***DEV NOTE:*** Above, briefly explain the benefits of using Prisma ORM with the specified framework after `it creates a...` ::: In this guide, you'll learn to integrate Prisma ORM with a Prisma Postgres database in a __________ project from scratch. You can find a complete example of this guide on [GitHub](https://github.com/prisma/prisma-examples/tree/latest/orm/__________). ## Prerequisites - [Node.js 18+](https://nodejs.org) ## 1. Set up your project ## 2. Install and Configure Prisma ### 2.1. Install dependencies To get started with Prisma, you'll need to install a few dependencies: ```terminal npm install prisma --save-dev npm install tsx --save-dev npm install @prisma/extension-accelerate ``` :::info If you're not using a Prisma Postgres database, you can skip `@prisma/extension-accelerate`. ::: Once installed, initialize Prisma in your project: :::warning ***DEV NOTE:*** Make sure you update the output path accordingly with the framework (ie. Next.js is `../app/generated/prisma`). and follow through with the proper import paths going forward. This template will be using `../generated/prisma`. ::: ```terminal npx prisma init --db --output ../generated/prisma ``` :::info You'll need to answer a few questions while setting up your Prisma Postgres database. Select the region closest to your location and a memorable name for your database like "My __________ Project" ::: This will create: - A `prisma/` directory with a `schema.prisma` file - A `.env` file with a `DATABASE_URL` already set ### 2.2. Define your Prisma Schema In the `prisma/schema.prisma` file, add the following models: :::warning ***DEV NOTE:*** If using Vite, the generator client should not include `-js` in the provider: ```prisma file=prisma/schema.prisma generator client { //add-next-line provider = "prisma-client" //delete-next-line provider = "prisma-client-js" output = "../generated/prisma" } ``` In addition, update the text above this and add "*and change the generator to use the `prisma-client` provider*" ::: ```prisma file=prisma/schema.prisma generator client { provider = "prisma-client-js" output = "../generated/prisma" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } //add-start model User { id Int @id @default(autoincrement()) email String @unique name String? posts Post[] } model Post { id Int @id @default(autoincrement()) title String content String? published Boolean @default(false) authorId Int author User @relation(fields: [authorId], references: [id]) } //add-end ``` This creates two models: `User` and `Post`, with a one-to-many relationship between them. ### 2.3. Configure the Prisma Client generator Now, run the following command to create the database tables and generate the Prisma Client: ```terminal npx prisma migrate dev --name init ``` ### 2.4. Seed the database Let's add some seed data to populate the database with sample users and posts. Create a new file called `seed.ts` in the `prisma/` directory: ```typescript file=prisma/seed.ts showLineNumbers //add-next-line import { PrismaClient, Prisma } from "../src/generated/prisma"; //add-next-line const prisma = new PrismaClient(); //add-start const userData: Prisma.UserCreateInput[] = [ { name: "Alice", email: "alice@prisma.io", posts: { create: [ { title: "Join the Prisma Discord", content: "https://pris.ly/discord", published: true, }, { title: "Prisma on YouTube", content: "https://pris.ly/youtube", }, ], }, }, { name: "Bob", email: "bob@prisma.io", posts: { create: [ { title: "Follow Prisma on Twitter", content: "https://www.twitter.com/prisma", published: true, }, ], }, }, ]; //add-end //add-start export async function main() { for (const u of userData) { await prisma.user.create({ data: u }); } } //add-end //add-next-line main(); ``` Now, tell Prisma how to run this script by updating your `package.json`: ```json file=package.json //add-start "prisma": { "seed": "tsx prisma/seed.ts" } //add-end ``` Run the seed script: ```terminal npx prisma db seed ``` And open Prisma Studio to inspect your data: ```terminal npx prisma studio ``` ## 3. Integrate Prisma into __________ ### 3.1. Create a Prisma Client Create a `/lib` directory and a `prisma.ts` file inside it. This file will be used to create and export your Prisma Client instance. Set up the Prisma client like this: <TabbedContent code> <TabItem value="Prisma Postgres (recommended)"> ```tsx file=src/lib/prisma.ts showLineNumbers import { PrismaClient } from "../generated/prisma"; import { withAccelerate } from "@prisma/extension-accelerate"; const prisma = new PrismaClient().$extends(withAccelerate()); export default prisma; ``` </TabItem> <TabItem value="Other databases"> ```tsx file=src/lib/prisma.ts showLineNumbers import { PrismaClient } from "../generated/prisma"; const prisma = new PrismaClient(); export default prisma; ``` </TabItem> </TabbedContent> :::warning We recommend using a connection pooler (like [Prisma Accelerate](https://www.prisma.io/accelerate)) to manage database connections efficiently. If you choose not to use one, **avoid** instantiating `PrismaClient` globally in long-lived environments. Instead, create and dispose of the client per request to prevent exhausting your database connections. ::: ### 3.2. :::warning ***DEV NOTE:*** How do you implement prisma into the framework? ::: You're done! You've just created a __________ app with Prisma ORM. Below are some next steps to explore, as well as some more resources to help you get started expanding your project. ## Next Steps Now that you have a working __________ app connected to a Prisma Postgres database, you can: - Extend your Prisma schema with more models and relationships - Add create/update/delete routes and forms - Explore authentication and validation - Enable query caching with [Prisma Postgres](/postgres/caching) for better performance ### More Info - [Prisma Documentation](/orm/overview/introduction) - [__________ Documentation](https://example.com/) ```` ## Next steps After reading this guide, you can: - Start writing your own guide using the provided structure - Review existing guides for reference - Request a unique header image for your guide - Submit your guide for review For more information: - [Prisma documentation style guide](/about/style-guide) - [Documentation components](/about/docs-components) --- # Guides URL: https://www.prisma.io/docs/guides/index Welcome to the Guides section! Here you'll find practical, step-by-step guides to help you accomplish specific tasks with Prisma products, including Prisma ORM, Prisma Accelerate, Prisma Postgres, and more. Browse through our guides below or use the search to find specific topics. ## Available Guides <DocCardList />