# Views (/docs/orm/prisma-schema/data-model/views)

Location: ORM > Prisma Schema > Data Model > Views

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:

1. [Enable the `views` preview feature](#enable-the-views-preview-feature)
2. [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
3. [Represent the view in your Prisma schema](#add-views-to-your-prisma-schema)
4. [Query the view in Prisma Client](#query-views-in-prisma-client)

> [!WARNING]
> Support for views is currently a [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. <br /><br />For updates on progress with this feature, follow [our GitHub issue](https://github.com/prisma/prisma/issues/17335).

Enable the views preview feature [#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 title="schema.prisma" highlight=3;add showLineNumbers
generator client {
  provider        = "prisma-client"
  output          = "./generated"
  previewFeatures = ["views"] // [!code ++]
}
```

Please leave feedback about this preview feature in our dedicated preview feature [feedback issue](https://github.com/prisma/prisma/issues/17335) for `views`.

Create a view in the underlying database [#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 or `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:

  

#### Relational databases

```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
}
```

#### MongoDB

```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 [#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 [#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:

  

#### Relational databases

```prisma
view UserInfo {
  id    Int
  email String
  name  String
  bio   String
}
```

#### MongoDB

```prisma
view UserInfo {
  id    String @map("_id") @db.ObjectId
  email String
  name  String
  bio   String
}
```

Write by hand [#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 [#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 [#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:

  

#### Relational databases

```prisma highlight=2-5;normal 
view UserInfo {
  id    Int // [!code highlight]
  email String // [!code highlight]
  name  String // [!code highlight]
  bio   String // [!code highlight]
}
```

#### MongoDB

```prisma highlight=2-5;normal 
view UserInfo {
  id    String @map("_id") @db.ObjectId // [!code highlight]
  email String // [!code highlight]
  name  String // [!code highlight]
  bio   String // [!code highlight]
}
```

Each *field* of a `view` block represents a column in the query results of the view in the underlying database.

Use introspection [#use-introspection]

> [!WARNING]
> Currently views can only be introspected with PostgreSQL, MySQL, SQL Server and CockroachDB databases. If you are using another database provider, your views must be added manually.

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:

  

#### npm

```bash
npx prisma db pull
```

#### pnpm

```bash
pnpm dlx prisma db pull
```

#### yarn

```bash
yarn dlx prisma db pull
```

#### bun

```bash
bunx --bun prisma db pull
```

The resulting `view` block will be defined as follows:

```prisma
view UserInfo {
  id    Int?
  email String?
  name  String?
  bio   String?
}
```

> [!WARNING]
> 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.

The views directory [#the-views-directory]

Introspection of a database with one or more existing views will also create a new `views` directory within your `prisma` directory. 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"))
  );
```

Query views in Prisma Client [#query-views-in-prisma-client]

> [!NOTE]
> Be sure to run `prisma generate` after updating your Prisma schema so that the `view` definitions become part of your Prisma Client API.

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",
  },
});
```

> [!NOTE]
> Write-queries (create/update/delete) are not supported on `views`.

Special types of views [#special-types-of-views]

This section describes how to use Prisma ORM with updatable and materialized views in your database.

Updatable views [#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 creating, updating, or deleting entries if the underlying database supports such operations.

Prisma ORM does not allow any mutations (create, update, delete) on views, regardless of the database's capabilities. This change provides guardrails to ensure that views are treated consistently as read-only entities within Prisma Client. As a result, methods to perform writes such as `create`, `update`, `delete`, or `upsert` are not generated for `view` blocks in your Prisma Client API.

If you need to modify data represented by a view, you must perform the write operations directly on the underlying tables or use raw SQL queries.

Materialized views [#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.

Limitations [#limitations]

Prisma ORM treats all `view` blocks as *read-only* representations of database queries rather than true tables. Because of this, several limitations apply to ensure Prisma Client remains consistent with the behavior of the underlying database.

No identifiers [#no-identifiers]

Views are virtual tables and do not have inherent primary keys. Hence, you cannot define `@id`, `@@id` attributes on a `view` block.

No indexes [#no-indexes]

Because views are virtual tables, they cannot have indexes. Therefore, `@index` and `@@index` cannot be defined on `view` blocks.

Unsafe @unique attributes [#unsafe-unique-attributes]

While Prisma ORM lets you place `@unique` and `@@unique` attributes on views, the underlying database and Prisma do not enforce those constraints. Multiple rows can therefore share the same value for a supposedly unique field.

Neither the database nor Prisma ORM enforce the unique constraint expressed by that attribute.

The purpose of the `@unique` attribute in this case is only to enable relationships across views as well as `findUnique` queries and cursor-based pagination in Prisma Client.

Disabled write queries [#disabled-write-queries]

All write operations (`create`, `update`, `delete`, `upsert`) are disabled and not generated in the Prisma Client.

## Related pages

- [`Database mapping`](https://www.prisma.io/docs/orm/prisma-schema/data-model/database-mapping): Learn how to map model and field names to database tables and columns
- [`External tables`](https://www.prisma.io/docs/orm/prisma-schema/data-model/externally-managed-tables): How to declare and use externally managed tables in Prisma ORM
- [`Indexes`](https://www.prisma.io/docs/orm/prisma-schema/data-model/indexes): How to configure index functionality and add full text indexes
- [`Models`](https://www.prisma.io/docs/orm/prisma-schema/data-model/models): Learn about the concepts for building your data model with Prisma: Models, scalar types, enums, attributes, functions, IDs, default values and more
- [`Multi-schema`](https://www.prisma.io/docs/orm/prisma-schema/data-model/multi-schema): How to use Prisma ORM with multiple database schemas