跳到主要内容

内省

你可以使用 Prisma CLI 内省你的数据库,以便在你的 Prisma 模式中生成数据模型。需要数据模型来生成 Prisma 客户端

将 Prisma ORM 添加到现有项目时,内省通常用于生成数据模型的初始版本。

然而,它也可以在应用程序中重复使用。当你不使用 Prisma Migrate,而是使用纯 SQL 或其他迁移工具执行模式迁移时,这种情况最为常见。在这种情况下,你还需要重新内省你的数据库,并随后重新生成 Prisma 客户端,以反映你的 Prisma Client API 中的模式更改。

内省的作用是什么?

内省有一个主要功能:使用反映当前数据库模式的数据模型填充你的 Prisma 模式。

Introspect your database with Prisma

以下是在 SQL 数据库上的主要功能的概述

  • 将数据库中的映射到 Prisma 模型
  • 将数据库中的映射到 Prisma 模型的字段
  • 将数据库中的索引映射到 Prisma 模式中的索引
  • 数据库约束映射到 Prisma 模式中的属性类型修饰符

在 MongoDB 上,主要功能如下

  • 将数据库中的集合映射到 Prisma 模型。由于 MongoDB 中的集合没有预定义的结构,Prisma ORM 会采样集合中的文档,并相应地推导出模型结构(即,它将文档的字段映射到 Prisma 模型的字段)。如果在集合中检测到嵌入式类型,这些类型将被映射到 Prisma 模式中的复合类型
  • 如果集合中至少包含一个包含索引中包含的字段的文档,则将数据库中的索引映射到 Prisma 模式中的索引

你可以在相应的数据源连接器文档页面上了解更多关于 Prisma ORM 如何将数据库中的类型映射到 Prisma 模式中可用的类型的信息

prisma db pull 命令

你可以使用 Prisma CLIprisma db pull 命令来内省你的数据库。请注意,使用此命令需要你的 连接 URL 在你的 Prisma 模式datasource中设置。

以下是 prisma db pull 在内部执行的步骤的高级概述

  1. 从 Prisma 模式中的 datasource 配置中读取连接 URL
  2. 打开与数据库的连接
  3. 内省数据库模式(即,读取表、列和其他结构...)
  4. 将数据库模式转换为 Prisma 模式数据模型
  5. 将数据模型写入 Prisma 模式或更新现有模式

内省工作流程

不使用 Prisma Migrate,而是使用纯 SQL 或其他迁移工具的项目的一般工作流程如下

  1. 更改数据库模式(例如,使用纯 SQL)
  2. 运行 prisma db pull 以更新 Prisma 模式
  3. 运行 prisma generate 以更新 Prisma 客户端
  4. 在你的应用程序中使用更新的 Prisma 客户端

请注意,随着应用程序的发展,这个过程可以重复无限次

Introspect workflow

规则和约定

Prisma ORM 采用许多约定来将数据库模式转换为 Prisma 模式中的数据模型

模型、字段和枚举名称

字段、模型和枚举名称(标识符)必须以字母开头,并且通常只能包含下划线、字母和数字。你可以在各自的文档页面上找到每个标识符的命名规则和约定

标识符的一般规则是它们需要遵循这个正则表达式

[A-Za-z][A-Za-z0-9_]*

无效字符的清理

无效字符在内省期间被清理

  • 如果它们出现在标识符中的字母之前,则会被删除。
  • 如果它们出现在第一个字母之后,则会被下划线替换。

此外,转换后的名称使用 @map@@map 映射到数据库,以保留原始名称。

考虑以下表格作为示例

CREATE TABLE "42User" (
_id SERIAL PRIMARY KEY,
_name VARCHAR(255),
two$two INTEGER
);

由于表名中的前导 42 以及列上的前导下划线和 $ 在 Prisma ORM 中被禁止,因此内省会添加 @map@@map 属性,以便这些名称符合 Prisma ORM 的命名约定

model User {
id Int @id @default(autoincrement()) @map("_id")
name String? @map("_name")
two_two Int? @map("two$two")

@@map("42User")
}

清理后重复的标识符

如果清理导致重复的标识符,则不会立即进行错误处理。你稍后会收到错误,并且可以手动修复它。

考虑以下两个表的情况

CREATE TABLE "42User" (
_id SERIAL PRIMARY KEY
);

CREATE TABLE "24User" (
_id SERIAL PRIMARY KEY
);

这将导致以下内省结果

model User {
id Int @id @default(autoincrement()) @map("_id")

@@map("42User")
}

model User {
id Int @id @default(autoincrement()) @map("_id")

@@map("24User")
}

尝试使用 prisma generate 生成你的 Prisma 客户端,你将收到以下错误

npx prisma generate
显示CLI结果
$ 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

在这种情况下,你必须手动更改两个生成的 User 模型之一的名称,因为 Prisma 模式中不允许重复的模型名称。

字段顺序

内省以与数据库中相应表列相同的顺序列出模型字段。

属性顺序

内省按照以下顺序添加属性(此顺序由 prisma format 反映)

  • 块级:@@id@@unique@@index@@map
  • 字段级:@id@unique@default@updatedAt@map@relation

关系

Prisma ORM 将在你的数据库表中定义的外键转换为关系

一对一关系

当表上的外键具有 UNIQUE 约束时,Prisma ORM 会将一对一关系添加到你的数据模型中,例如

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 将其转换为以下数据模型

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])
}

一对多关系

默认情况下,Prisma ORM 会将一对多关系添加到你的数据模型中,以表示它在你的数据库模式中找到的外键

CREATE TABLE "User" (
id SERIAL PRIMARY KEY
);
CREATE TABLE "Post" (
id SERIAL PRIMARY KEY,
"author" integer NOT NULL,
FOREIGN KEY ("author") REFERENCES "User"(id)
);

这些表被转换为以下模型

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])
}

多对多关系

多对多关系通常在关系数据库中表示为关系表

Prisma ORM 支持在 Prisma 模式中定义多对多关系的两种方式

如果隐式多对多关系符合 Prisma ORM 的 关系表约定,则会被识别。否则,关系表会在 Prisma 模式中渲染为一个模型(因此成为一个显式多对多关系)。

关于关系的文档页面对此主题进行了广泛的介绍。

消除关系歧义

Prisma ORM 通常会在 @relation 属性上省略 name 参数,如果不需要的话。考虑上一节中的 UserPost 示例。 @relation 属性只有 references 参数,省略了 name,因为在这种情况下不需要它。

model Post {
id Int @id @default(autoincrement())
author Int
User User @relation(fields: [author], references: [id])
}

如果 Post 表上定义了两个外键,则需要该参数。

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 需要使用专用的关系名称来消除关系的歧义

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

请注意,您可以将Prisma-ORM 级别关系字段重命名为任何您喜欢的名称,以便在生成的 Prisma Client API 中看起来更友好。

使用现有模式进行自省

对于具有现有 Prisma 模式的关系数据库,运行 prisma db pull 会将对模式进行的手动更改与数据库中所做的更改合并。(此功能首次在 2.6.0 版本中添加。)对于 MongoDB,自省目前仅用于初始数据模型。重复运行会导致自定义更改丢失,如下所示。

关系数据库的自省会保留以下手动更改

  • model 块的顺序
  • enum 块的顺序
  • 注释
  • @map@@map 属性
  • @updatedAt
  • @default(cuid()) (cuid() 是 Prisma-ORM 级别的函数)
  • @default(uuid()) (uuid() 是 Prisma-ORM 级别的函数)
  • 自定义 @relation 名称

注意:只会提取数据库级别的模型之间的关系。这意味着必须设置外键

模式的以下属性由数据库确定

  • model 块内字段的顺序
  • enum 块内值的顺序

注意:所有 enum 块都列在 model 块的下面。

强制覆盖

要覆盖手动更改,并仅基于自省的数据库生成模式,并忽略任何现有的 Prisma 模式,请将 --force 标志添加到 db pull 命令中

npx prisma db pull --force

用例包括

  • 您想从头开始使用从底层数据库生成的模式
  • 您的模式无效,必须使用 --force 才能使自省成功

仅自省数据库模式的子集

仅自省数据库模式的子集尚未得到 Prisma ORM 的 官方支持

但是,您可以通过创建一个新的数据库用户来实现此目的,该用户仅有权访问您希望在 Prisma 模式中表示的表,然后使用该用户执行自省。自省将仅包括新用户有权访问的表。

如果您的目标是从 Prisma Client 生成中排除某些模型,您可以在 Prisma 模式中的模型定义中添加 @@ignore 属性。被忽略的模型将从生成的 Prisma Client 中排除。

关于不支持功能的自省警告

Prisma 模式语言 (PSL) 可以表达 Prisma ORM 支持的目标数据库的大部分数据库功能。但是,Prisma 模式语言仍然需要表达一些特性和功能。

对于这些功能,Prisma CLI 将在您的数据库中检测到该功能的使用并返回警告。Prisma CLI 还将在 Prisma 模式中使用这些功能的模型和字段中添加注释。警告还将包含一个解决方法建议。

prisma db pull 命令将显示以下不支持的功能

您可以在 GitHub 上找到我们计划支持的功能列表(标记为 topic:database-functionality

针对不支持的功能的自省警告的解决方法

如果您正在使用关系数据库,并且使用了上一节中列出的上述功能之一

  1. 创建一个草稿迁移
    npx prisma migrate dev --create-only
  2. 添加在警告中显示的功能的 SQL。
  3. 将草稿迁移应用到您的数据库
    npx prisma migrate dev