Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 137 additions & 9 deletions content/200-concepts/100-components/01-prisma-schema/08-views.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ tocDepth: 2

<Admonition type="warning">

Support for views is currently a very early preview feature. You can add a view to your Prisma schema with the `view` keyword, but you cannot introspect your schema with `db pull` or apply your schema to your database with Prisma Migrate and `db push`.<br /><br />For updates on progress with this feature, follow [our GitHub issue](https://github.com/prisma/prisma/issues/17335).
Support for views is currently a very early [Preview](/about/prisma/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).

</Admonition>

Expand Down Expand Up @@ -94,7 +94,7 @@ For a relational database, the SQL statement to create this view is:
CREATE VIEW "UserInfo" AS
SELECT u.id, email, name, bio
FROM "User" u
LEFT JOIN "Profile" p ON u.id = p."userId"
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:
Expand Down Expand Up @@ -123,7 +123,7 @@ db.createView('UserInfo', 'User', [

## Use views with Prisma Migrate and <inlineCode>db push</inlineCode>

If you apply changes to your schema with Prisma Migrate or `db push`, Prisma does not create or run any SQL related to views.
If you apply changes to your Prisma schema with Prisma Migrate or `db push`, Prisma 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.

Expand All @@ -140,7 +140,7 @@ You can represent the `UserInfo` view from the example above in your Prisma sche

```prisma
view UserInfo {
id Int @id
id Int @unique
email String
name String
bio String
Expand All @@ -164,20 +164,148 @@ view UserInfo {

<!-- prettier-ignore-end -->

### Limitations
### 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

Currently, Prisma treats views in the same way as models. This means that a view needs to have a [unique identifier](/concepts/components/prisma-schema/data-model#defining-an-id-field). In relational databases, this can be an `@id` or `@unique` attribute on one field, or an `@@id` or `@@unique` attribute on multiple fields. In MongoDB, this must be an `@id` attribute that maps to the `_id` field in the underlying database with `@map("_id")`.
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
}
```

In the example above, the `id` field has an `@id` attribute.
<!-- It would be good to reference some recommended naming conventions as we do for `model` blocks -->

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

<TabbedContent tabs={[<FileWithIcon text="Relational databases" icon="database"/>, <FileWithIcon text="MongoDB" icon="database"/>]}>
<tab>

```prisma highlight=2-5;normal
view UserInfo {
id Int @unique
email String
name String
bio String
}
```

</tab>
<tab>

```prisma highlight=2-5;normal
view UserInfo {
id String @id @default(auto()) @map("_id") @db.ObjectId
Comment thread
sabinadams marked this conversation as resolved.
email String
name String
bio String
}
```

</tab>
</TabbedContent>

Prisma does not currently support introspection of views with `db pull`. Instead, you must manually add views to your Prisma schema.
Each _field_ of a `view` block represents a column in the query results of the view in the underlying database.

### Use introspection

<Admonition type="warning">
Currently only available for PostgreSQL.
</Admonition>

If you have an existing view or views defined in your database, [introspection](/concepts/components/introspection) will automatically generate `view` blocks in your Prisma schema that represent those views.
Comment thread
sabinadams marked this conversation as resolved.

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:

```sh 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 the Prisma Client.
view UserInfo {
Comment thread
janpio marked this conversation as resolved.
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).

In this view's case, the `id` column refers to a uniquely identifiable field in the underlying `User` table so that field will 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 comment Prisma generated warning about an invalid view

```prisma highlight=4;add|1,3,8,9;delete
/// The underlying view does not contain a valid unique identifier and can therefore currently not be handled by the Prisma Client.
view UserInfo {
id Int?
id Int @unique
email String?
name String?
bio String?

@@ignore
}
```

When re-introspecting your database, any custom changes to your view definitions will be preserved.

<Admonition type="warning">

Currently, if you introspect your database, Prisma removes any existing `view` blocks in your schema file. To reinstate the views, you must revert this change.
Please note for now `db pull` will only introspect views in your schema when using PostgreSQL. Support for this workflow will be extended to other database providers soon.

</Admonition>

### Limitations

#### Unique Identifier

Currently, Prisma 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`](/concepts/components/prisma-schema/data-model#defining-a-unique-field)
- A composite unique constraint denoted with [`@@unique`](/concepts/components/prisma-schema/data-model#defining-a-unique-field)
- An [`@id`](/concepts/components/prisma-schema/data-model#defining-an-id-field) field
- A composite identifier denoted with [`@@id`](/concepts/components/prisma-schema/data-model#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. 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 soon 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.
Expand Down