跳至主要内容

升级 Prisma ORM 层

概述

此页面解释了升级流程的第一步:使用 Prisma 1 配置并将其升级到 Prisma ORM 2。具体来说,您将学习如何

  1. 将 Prisma ORM 2 CLI 添加为开发依赖项
  2. 创建您的 Prisma ORM 2 架构
  3. 确定您的连接 URL 并连接到您的数据库
  4. 内省您的数据库(到目前为止一直使用 Prisma 1 管理)
  5. 使用 Prisma 1 升级 CLI 来解决新 Prisma ORM 2 数据模型中的 架构不兼容性
  6. 安装并生成 Prisma 客户端

完成这些步骤后,您可以继续进行下一步指南,该指南解释了如何升级应用程序层以使用 Prisma 客户端进行数据库查询。

注意:在升级过程中,获得数据库的图形视图可能会有所帮助。因此,建议使用图形数据库客户端连接到您的数据库,例如 TablePlusPostico

1. 安装 Prisma ORM 2 CLI

Prisma ORM 2 CLI 可作为 prisma 包在 npm 上获得,并通过 prisma 命令调用。

请注意,以前用于 Prisma 1 的 prisma 命令已重命名为 prisma1。您可以了解更多关于 此处的信息。

您可以按照以下步骤在您的 Node.js 项目中安装 Prisma ORM 2 CLI(确保在 package.json 所在的目录中调用此命令)

npm install prisma --save-dev

注意:使用 Prisma 1 时,通常建议全局安装 CLI。我们现在建议 在本地安装 Prisma CLI 以防止版本冲突。

您现在可以使用 prisma CLI 的本地安装,方法是在其前面加上 npx

npx prisma

如果您要 一次性 升级整个项目,您现在也可以卸载 Prisma 1 CLI(否则请展开下面的内容)

# remove global installation
npm uninstall -g prisma1

# remove local installation
npm uninstall prisma1

如果您想并行使用 Prisma 1 CLI,请展开

如果您想继续使用 Prisma 1 CLI,建议您删除其全局安装并添加 prisma1 CLI 作为开发依赖项

# installs v1.34 of the Prisma 1 CLI
npm uninstall -g prisma
npm install prisma1 --save-dev

您现在可以按如下方式调用它

npx prisma1

请注意,如果您需要低于 1.34 的 CLI 版本(例如 1.30),您可以按如下方式安装它

# installs v1.30 of the Prisma 1 CLI
npm uninstall -g [email protected]
npm install [email protected] --save-dev

您现在可以按如下方式调用它

npx prisma

2. 创建您的 Prisma ORM 2 架构

对于本指南,您将首先使用 prisma init 命令创建一个新的 Prisma 架构,然后使用 内省 用数据模型“填充”它。

运行以下命令创建您的 Prisma 架构(请注意,如果您已经有了一个名为 prisma 的文件夹,则此命令会抛出错误)

npx prisma init

如果您看到以下错误,则需要重命名您当前的 prisma 目录

ERROR  A folder called prisma already exists in your project.
Please try again in a project that is not yet using Prisma.

您可以将当前的 prisma 目录重命名为 prisma1,以明确表明它包含以前的 Prisma 1 配置

mv prisma prisma1

现在您可以运行 init,它应该成功

npx 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 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

该命令创建了一个名为 prisma 的新文件夹,以及两个文件

  • prisma/schema.prisma:您的 Prisma 架构,用于指定 数据源生成器数据模型(请注意,数据模型尚不存在,它将通过内省生成)。
  • .env:一个 dotenv 文件,用于配置您的数据库 连接 URL

您的初始 Prisma 架构如下所示

schema.prisma
// 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"
}

使用 Prisma 1 时,您会在 prisma.yml 中指定要使用的 Prisma 客户端的语言变体。使用 Prisma ORM 2 时,此信息现在通过 generator 块在 Prisma 架构中指定。

注意:与 Prisma 1 不同,Prisma 客户端 2.0 的 TypeScript 和 JavaScript 变体使用名为 prisma-client-js相同生成器。即使在普通 JavaScript 项目中,index.d.ts 中的生成的类型也始终包含在内。这使得即使在不使用 TypeScript 的情况下,VS Code 中的功能也能像自动完成一样。

3. 确定您的连接 URL 并连接到您的数据库

使用 Prisma 1 时,数据库连接在用于启动 Prisma ORM 服务器的 Docker Compose 文件中配置。然后,Prisma ORM 服务器会公开一个 GraphQL 端点(通过 HTTP),该端点会代理 Prisma 客户端应用程序代码中的所有数据库请求。该 HTTP 端点在您的 prisma.yml 中指定。

使用 Prisma ORM 2 时,HTTP 层不再公开,Prisma 客户端 2.0 被配置为“直接”对数据库运行请求(也就是说,请求由 Prisma ORM 的 查询引擎 代理,但不再有额外的服务器)。

因此,作为下一步,您需要告诉 Prisma ORM 2 您使用的是哪种数据库(MySQL 或 PostgreSQL)以及它位于哪里

首先,您需要确保 schema.prismadatasource 块上的 provider 字段被配置为使用正确的数据库

  • 如果您使用的是 PostgreSQL,则需要在 provider 字段中定义值 "postgresql"
  • 如果您使用的是 MySQL,则需要在 provider 字段中定义值 "mysql"

切换代码块中的制表符以查看这两个示例

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

设置好 provider 字段后,您就可以在 .env 文件中配置连接 URL。

假设用于部署 Prisma ORM 服务器的 Docker Compose 文件中的数据库配置如下所示

docker-compose.yml
PRISMA_CONFIG: |
port: 4466
databases:
default:
connector: postgres
host: postgres
port: 5432
user: prisma
password: prisma

另外,假设您的 prisma.yml 中的 endpoint 配置如下所示

prisma.yml
endpoint: http://127.0.0.1:4466/myproject/dev

根据这些连接详细信息,您需要在 .env 文件中配置 DATABASE_URL 环境变量,如下所示

.env
DATABASE_URL="postgresql://janedoe:randompassword@localhost:5432/prisma?schema=myproject$dev"

请注意,schema 参数通常由您的服务名称服务阶段(它们是 prisma.ymlendpoint 的一部分)组成,用 $ 字符分隔。

有时 prisma.yml 中未指定服务名称和阶段

prisma.yml
endpoint: http://127.0.0.1:4466/

在这种情况下,schema 必须按如下方式指定

.env
DATABASE_URL="postgresql://janedoe:randompassword@localhost:5432/prisma?schema=default$default"

连接 URL 页面上了解更多信息。

4. 内省您的数据库

在本指南中,我们将使用以下 Prisma 1 数据模型(选择下面的SQL 选项卡查看数据模型在 SQL 中映射的内容)

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
}

请注意,此数据模型具有三个 关系

  • 1-1:UserProfile
  • 1-n:UserPost(通过 _PostToUser 关系表维护)
  • m-n:PostCategory(通过 _CategoryToPost 关系表维护)

现在,您可以使用以下命令对您的数据库运行 Prisma ORM 的内省

npx prisma db pull

以下是 db pull 被调用时发生的情况的图形说明

Introspect your database

对于上述 Prisma 1 数据模型,这将产生以下 Prisma ORM 2 架构(请注意,模型已重新排序以匹配 Prisma 1 数据模型的初始顺序)

schema.prisma
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[]
}

虽然这已经是有效的 Prisma ORM 2 架构,但它缺少其 Prisma 1 等效项中的一些功能

  • PostcreatedAtupdatedAt 字段没有自动生成的日期值。
  • Userrole 字段没有默认值。
  • Postpublished 字段没有默认值。

此外,还有一些不一致之处,导致 Prisma Client API 变得不那么习惯/符合人体工程学。

  • UserProfile 是 1-n 关系而不是 1-1 关系。
  • UserPost 是 m-n 关系而不是 1-n 关系。
  • 关系字段是大写字母(例如,User 上的 ProfilePost)。
  • User 上的 jsonData 字段类型是 String 而不是 Json
  • User 上的 role 字段类型是 String 而不是 Role,角色的 enum 定义完全缺失。

虽然这些不一致之处不会实际影响到 Prisma Client API 中可用的“功能集”,但它们会导致您失去之前存在的某些约束/保证。

例如,Prisma ORM 现在无法保证一个 User 最多连接到一个 Profile,因为在内省过程中,表之间的关系被识别为 1-n,因此一个 User 记录现在可能会连接到多个 Profile 记录。

另一个问题是,您可以为 jsonDatarole 字段存储任何文本,无论它是否为有效的 JSON 还是表示 Role 枚举的值。

要详细了解这些不一致之处,请查看 Schema 不兼容 页面。

在下文中,我们将逐一介绍这些不兼容之处,并使用 Prisma 模式升级 CLI 来修复它们。

5. 使用 Prisma 模式升级 CLI 来解决模式不兼容

Prisma 1 升级 CLI 是一个交互式工具,可以帮助您升级 Prisma 模式并解决上面列出的大多数不一致之处。

Prisma 1 升级 CLI 分两个主要阶段进行。

  1. 通过纯 SQL 修复数据库模式。
  2. 在 Prisma ORM 2 模式中添加缺失的属性以及其他模式修复。

在第一阶段,它将生成并打印一些 SQL 语句,您应该在您的数据库上运行这些语句来调整数据库模式。您可以在继续进行第二阶段之前运行所有语句或其中的一部分。

在第二阶段,您无需手动操作。升级 CLI 将通过添加某些 Prisma ORM 级别的属性(例如 @default(cuid))@updatedAt)来修改 Prisma 模式,调整关系字段的名称以匹配您的 Prisma 1 数据模型中的名称,并确保在您的 Prisma 1 数据模型中两边都需要的一对一关系也在 Prisma ORM 2 模式中是必需的。

请注意,**您可以在此过程中的任何时候重新开始**,从第二阶段返回到第一阶段。

在本图示中,绿色区域表示第一阶段,蓝色区域表示第二阶段。请注意,您可以在阶段之间选择运行 prisma db pull 以更新您的 Prisma ORM 数据模型。

Fixing the schema incompatibilities

要使用升级 CLI,您可以将其本地安装到您的项目中,或者像这里一样使用 npx 一次性调用它,而无需安装。

npx prisma-upgrade prisma1/prisma.yml prisma/schema.prisma

CLI 将用以下消息向您问候。

◮ 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/upgrade/issues/new

Are you ready? [Y/n]

按下 Y 按钮,然后按键盘上的 RETURN 键确认以继续。

确认后,CLI 将输出您应该在数据库上运行的 SQL 语句。

➤ 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'

注意:如果您看到有关重大更改的注释,现在可以忽略它。我们稍后会讨论它。

显示的 SQL 语句分为多个“桶”,所有这些语句都旨在解决某些 模式不兼容

  • 修复具有 ENUM 数据类型的列。
  • 在数据库中添加缺失的 DEFAULT 约束。
  • 修复具有 JSON 数据类型的列。
  • 在 Prisma 2 中复制 @createdAt 行为。
  • 通过添加 UNIQUE 约束修复一对一关系。

下一步,您可以开始将 SQL 语句发送到您的数据库。请注意,所有这些更改都是非破坏性的,您将能够继续将 Prisma 1 与 Prisma ORM 2 并行使用。

接下来的部分将分别介绍要发送到数据库的不同类型的 SQL 语句。

5.1. 通过纯 SQL 修复数据库模式(非破坏性)

在本部分,我们将逐步介绍打印的 SQL 语句,并逐一在数据库上运行它们。

5.1.1. 修复具有 ENUM 数据类型的列

该工具首先做的就是帮助您确保 Prisma 1 数据模型中的 enum 定义将表示为底层数据库中的实际 ENUM 类型,现在它们表示为纯字符串(例如,在 MySQL 中表示为 MEDIUMTEXT)。

CLI 目前显示以下输出。

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";

⚠️ 警告:如果您正在并行运行 Prisma 1 和 Prisma ORM 2 并行,这些 SQL 语句将破坏您的 Prisma 1 设置。文档将很快更新以反映这一点。

现在,在您的数据库上运行这些语句。

Altering columns to use ENUM with SQL

5.1.2. 在数据库中添加缺失的 DEFAULT 约束

接下来,升级 CLI 通过生成在数据库中添加相应 DEFAULT 约束的 SQL 语句来帮助您解决 默认值未在数据库中表示 的问题。

在本例中,缺少两个 DEFAULT 约束,这些约束由该工具建议。

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;

现在,您可以使用命令行客户端或 Postico 等 GUI 在您的数据库上运行这些 SQL 语句。

Adding missing DEFAULT constraints to columns

5.1.3. 修复具有 JSON 数据类型的列

接下来,该工具帮助您确保 Prisma 1 数据模型中的 Json 字段将表示为底层数据库中的 JSON 列,现在它们表示为纯字符串(例如,在 MySQL 中表示为 MEDIUMTEXT)。

将列类型更改为 JSON 将确保在 Prisma ORM 2 内省过程中,该字段被正确识别为 Json

CLI 目前显示以下输出。

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;

⚠️ 警告:如果您正在并行运行 Prisma 1 和 Prisma ORM 2 并行,这些 SQL 语句将破坏您的 Prisma 1 设置。文档将很快更新以反映这一点。

现在,您可以使用命令行客户端或 Postico 等 GUI 在您的数据库上运行这些 SQL 语句。

Adding missing DEFAULT constraints to columns

5.1.4. 在 Prisma ORM 2 中复制 @createdAt 行为

该工具接下来做的就是帮助您解决 @createdAt 的行为未在数据库中表示 的问题。

CLI 目前显示以下输出。

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;

现在,您可以使用命令行客户端或 Postico 等 GUI 在您的数据库上运行这些 SQL 语句。

Running an SQL command to alter a column

5.1.5. 通过添加 UNIQUE 约束修复一对一关系

现在,该工具将帮助您 UserProfile 之间当前的 1-n 关系重新转换为 1-1 关系,方法是在数据库中添加一个 UNIQUE 约束到名为 user(以 Prisma 1 数据模型中的关系字段命名)的外键列。

CLI 目前显示以下输出。

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");

现在,您可以使用命令行客户端或 Postico 等 GUI 在您的数据库上运行这些 SQL 语句。

Running an SQL command to alter a column

5.1.6. 修复 CUID 长度不匹配

注意:即使您已更改底层数据库中的列类型,这些 SQL 语句仍将出现在升级 CLI 中。这目前是升级 CLI 的一个限制。

最后,该工具将帮助您 将当前类型为 VARCHAR(25) 的 ID 列转换为 VARCHAR(30),方法是在数据库中添加一个 UNIQUE 约束到名为 user(以 Prisma 1 数据模型中的关系字段命名)的外键列。

CLI 目前显示以下输出。

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);

现在,您可以使用命令行客户端或 Postico 等 GUI 在您的数据库上运行这些 SQL 语句。

Running an SQL command to alter a column

5.1.7. 检测到重大更改

如果升级 CLI 打印了一条关于重大更改的注释,那么您的数据库模式需要进行一些调整才能完全优化,这些调整将破坏 Prisma 1 兼容性。

如果没有检测到重大更改,您可以 跳到 5.2 部分

根据您的 升级策略,您可以现在执行这些更改,或者跳到升级 CLI 的下一个阶段。

  • 如果您遵循逐步并行升级策略,请不要立即执行这些更改,因为它们会破坏您的 Prisma 1 设置。在这种情况下,您可以通过键入 n 并按 RETURN 键继续进行升级 CLI 的下一个阶段。
  • 如果您遵循一次性升级策略,您现在可以执行这些更改。在这种情况下,通过键入 Y 并按 RETURN 键继续。

5.2. 通过纯 SQL 修复数据库模式(破坏性)

在本部分,您将解决破坏 Prisma 1 设置的模式不兼容问题。如果您仍在项目中运行 Prisma 1,请不要执行这些更改!

5.2.1. 修复不正确的 m-n 关系

现在,升级 CLI 帮助您修复 Prisma 1 用关系表表示的所有一对一和一对多关系,这些关系 目前在您的新 Prisma ORM 2 模式中仅作为 m-n 关系存在。具体而言,这就是 UserPost 关系的情况,该关系目前定义为 m-n,但实际上应该是一对多关系。

要修复此问题,您需要执行以下迁移。

  1. Post上创建一个新的外键列,直接链接到User表。
  2. 将外键值从关联表迁移到Post上的新外键列。
  3. 删除关联表。

这些说明现在由 CLI 打印。

➤ 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]?

为了解决此问题,您需要运行三个 SQL 语句。

  1. Post表上创建新的列authorId。此列应该是一个外键,引用User表的id字段。
    ALTER TABLE `Post` ADD COLUMN `authorId` VARCHAR(25);
    ALTER TABLE `Post` ADD FOREIGN KEY (`authorId`) REFERENCES `User` (`id`);
  2. 编写一个 SQL 查询,读取_PostToUser关联表中的所有行,并针对每一行
    1. 通过查找A列中的值来查找相应的Post记录。
    2. B列中的值作为authorId的值插入该Post记录。
    UPDATE Post, _PostToUser
    SET Post.authorId = _PostToUser.B
    WHERE Post.id = _PostToUser.A
  3. 删除_PostToUser关联表。
    DROP TABLE `_PostToUser`;

Fixing incorrect m-n relations with SQL

执行这些命令后,关联表B列中记录的用户 ID 值将被迁移到新的authorId列。

5.2. 重新检查您的数据库以更新您的 Prisma 架构

此时,您已经通过 Upgrade CLI 解决了架构不兼容问题。现在,您可以通过键入n并按RETURN退出 Upgrade CLI。

在本节中,您将通过另一轮自省来更新您的 Prisma 架构。这次,因为数据库架构已经调整,所以 Prisma 架构之前的缺陷将被解决。

npx prisma db pull

这次,生成的 Prisma 架构如下所示。

schema.prisma
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
}

此架构已经解决了大部分问题,但仍然缺少以下内容。

5.2. 向 Prisma 2 架构添加缺失的属性和其他架构修复

CLI 现在打印以下内容。

➤ 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]

此时,您已经运行了 CLI 打印的所有 SQL 语句,或者您跳过了一些语句。无论哪种方式,您现在都可以进入最后一步,并让 Upgrade CLI 添加缺失的 Prisma ORM 2 属性。通常情况下,这些属性包括:

  • @default(cuid()) 用于您的@id字段。
  • @updatedAt 用于在 Prisma 1 中使用此属性的任何字段。
  • @map@@map 作为 Prisma 1 中 @db@@db 的替代品。

在这一步中,Upgrade CLI 还修复了迁移到 Prisma ORM 2 时出现的其他问题。

  • 它确保在 Prisma 1 中两侧都需要的 1-1 关系在您的 Prisma ORM 2 架构中也是必需的。
  • 它将关系字段重命名为它们在您的 Prisma 1 数据模型中使用的相同名称(即将推出)。

要应用这些更改,您可以重新运行 Upgrade CLI。

npx prisma-upgrade prisma1/prisma.yml prisma/schema.prisma

如果您没有解决所有架构不兼容问题,Upgrade CLI 现在将打印剩余的 SQL 语句(以及用于迁移 ID 的语句)。此时,您可以忽略它们,并通过在提示时连续键入Y并按RETURN继续到最后一步。

如果您确实解决了所有架构不兼容问题,则不会打印任何 SQL 语句,Upgrade CLI 只输出以下内容。

$ 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]?

再次键入Y并按RETURN确认。

Upgrade CLI 的最后一个提示要求您确认它将对您的 Prisma 架构所做的上述更改。

➤ 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]

最后一次,键入Y并按RETURN确认。

这是 Upgrade CLI 的最终输出。

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. 最终结果

Prisma 架构的最终版本应如下所示。

schema.prisma
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. 重命名关系字段

您会注意到,在这个版本的 Prisma ORM 2 架构中,所有关系字段都以它们各自的模型命名,例如:

schema.prisma
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])
}

这不是理想的情况,实际上,您可以手动将它们全部重命名为以前的版本!

因为所有关系字段都是虚拟的,这意味着它们不会在数据库中表现出来,所以您可以随意命名它们。在本例中,所有关系字段都小写,有时还会进行复数化。

以下是在重命名后它们的样子。

schema.prisma
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])
}

注意:对于UserProfile之间的 1-1 关系,无法为关系字段设置旧的名称user。这是因为会与已存在的关系标量字段发生命名冲突,该字段保存外键。在这种情况下,您可以选择另一个名称,或者也可以通过 SQL 直接在数据库中重命名外键列。

5.5. 解决剩余的架构不兼容问题

Upgrade CLI 尚未解决一些架构不兼容问题。此时,您还没有修复标量列表。您可以在架构不兼容问题页面上找到针对此问题和其他问题的推荐解决方法。

6. 安装并生成 Prisma Client

现在您已经准备好了 Prisma ORM 2 架构,您可以使用以下命令安装 Prisma Client。

npm install @prisma/client

7. 后续步骤

恭喜您,您现在已经将 Prisma ORM 层升级到 Prisma ORM 2!从现在开始,您可以继续使用以下指南之一更新您的应用程序代码。

  • 旧版到新版 Nexus:如果您当前运行的是 Prisma 1 和 GraphQL Nexus,请选择本指南。
  • prisma-binding 到 Nexus:如果您当前运行的是 Prisma 1 和 prisma-binding,并且想要升级到Nexus(以及 TypeScript),请选择本指南。
  • prisma-binding 到 SDL-first:如果您当前运行的是 Prisma 1 和 prisma-binding,并且想要升级到SDL-first GraphQL 服务器,请选择本指南。
  • REST API:如果您当前正在使用 Prisma Client 1 运行 Prisma 1,并且正在构建 REST API,请选择本指南。

额外信息:Prisma Client API 比较

本节包含 Prisma 1 和 Prisma ORM 2 的 Prisma Client API 的高级别并排比较。有关新的 Prisma Client API 的更多详细信息,您可以探索Prisma Client 文档。

读取单个记录

Prisma Client (v1)
const user = await prisma.user({ id: 1 })
Prisma Client (v2)
await prisma.user.findUnique({
where: { id: 1 },
})

读取记录列表

Prisma Client (v1)
const user = await prisma.users()
Prisma Client (v2)
await prisma.user.findMany()

筛选列表

Prisma Client (v1)
const users = await prisma.users({
where: {
name: 'Alice',
},
})
Prisma Client (v2)
await prisma.user.findMany({
where: {
name: 'Alice',
},
})

对列表进行分页

Prisma Client (v1)
const posts = await prisma.posts({
skip: 5,
first: 10,
})
Prisma Client (v2)
await prisma.user.findMany({
skip: 5,
take: 10,
})

注意:您可以在相应的发行说明或文档中的分页页面中了解更多有关新的分页 API 的信息。

对列表进行排序

Prisma Client (v1)
await prisma.posts({
orderBy: 'title_ASC',
})
Prisma Client (v2)
await prisma.posts({
orderBy: {
title: 'asc',
},
})

创建记录

Prisma Client (v1)
await prisma.createUser({
name: 'Alice',
})
Prisma Client (v2)
await prisma.user.create({
data: {
name: 'Alice',
},
})

更新记录

Prisma Client (v1)
await prisma.updateUser({
where: { id: 1 },
data: {
name: 'James',
email: '[email protected]',
},
})
Prisma Client (v2)
await prisma.user.update({
where: { id: 1 },
data: {
name: 'James',
email: '[email protected]',
},
})

删除记录

Prisma Client (v1)
await prisma.deleteUser({ id: 1 })
Prisma Client (v2)
await prisma.user.delete({
where: { id: 1 },
})

选择字段和加载关系

在 Prisma 1 中,选择特定字段和/或加载对象关系的唯一方法是使用基于字符串的 $fragment$graphql 函数。使用 Prisma ORM 2,现在可以通过使用selectinclude以干净且类型安全的方式完成此操作。

这种方法的另一个好处是,您可以在任何 Prisma Client 查询上使用 selectinclude,例如 findUnique()findManycreateupdatedelete 等。

Prisma Client (v1)
await prisma.user({ id: 1 }).$fragment(`
fragment NameAndEmail on User { id email }`
`)
Prisma Client (v2)
await prisma.user.findUnique({
where: { id: 1 },
select: {
id: true,
email: true,
},
})

例如,在 Prisma 1 中,无法创建新记录并在返回的对象中只检索 id。使用 Prisma ORM 2,您可以通过以下方式实现此目标。

await prisma.user.create({
data: {
name: 'Alice',
},
select: {
id: true,
},
})