内省
您可以使用 Prisma CLI 内省您的数据库,以便在您的 数据模型 中生成 Prisma 模式。数据模型是 生成 Prisma Client 所需的。
内省通常用于在 将 Prisma ORM 添加到现有项目 时生成数据模型的初始版本。
但是,它也可以 在应用程序中反复使用。当您没有使用 Prisma Migrate,而是使用纯 SQL 或其他迁移工具执行模式迁移时,这种情况最常见。在这种情况下,您还需要重新内省您的数据库并随后重新生成 Prisma Client 以反映您 Prisma Client API 中的模式更改。
内省的作用是什么?
内省有一个主要功能:使用反映当前数据库模式的数据模型填充您的 Prisma 模式。
以下是它在 SQL 数据库上的主要功能概述
- 将数据库中的表映射到 Prisma 模型
- 将数据库中的列映射到 Prisma 模型的 字段
- 将数据库中的索引映射到 Prisma 模式中的 索引
- 将数据库约束映射到 Prisma 模式中的 属性 或 类型修饰符
在 MongoDB 上,主要功能如下
- 将数据库中的集合映射到 Prisma 模型。由于 MongoDB 中的集合没有预定义的结构,Prisma ORM 会采样集合中的文档并相应地推导出模型结构(即它将文档的字段映射到 Prisma 模型的 字段)。如果在集合中检测到嵌入式类型,这些类型将映射到 Prisma 模式中的 复合类型。
- 将数据库中的索引映射到 Prisma 模式中的 索引,如果集合中至少有一个文档包含索引中包含的字段
您可以从数据源连接器的相应文档页面中了解有关 Prisma ORM 如何将数据库中的类型映射到 Prisma 模式中可用类型的更多信息
prisma db pull
命令
您可以使用 Prisma CLI 的 prisma db pull
命令内省您的数据库。请注意,使用此命令需要在您的 Prisma 模式 连接 URL 设置在您的 Prisma 模式 datasource
中。
以下是 prisma db pull
在内部执行的步骤的高级概述
- 从 Prisma 模式中的
datasource
配置读取 连接 URL - 打开与数据库的连接
- 内省数据库模式(即读取表、列和其他结构...)
- 将数据库模式转换为 Prisma 模式数据模型
- 将数据模型写入 Prisma 模式或 更新现有模式
内省工作流程
对于未使用 Prisma Migrate 而是使用纯 SQL 或其他迁移工具的项目的典型工作流程如下
- 更改数据库模式(例如,使用纯 SQL)
- 运行
prisma db pull
以更新 Prisma 模式 - 运行
prisma generate
以更新 Prisma Client - 在您的应用程序中使用更新的 Prisma Client
请注意,随着应用程序的发展,此过程可以无限次重复。
规则和约定
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 Client,您将收到以下错误
npx prisma generate
$ 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
参数,除非需要它。考虑上一节中的 User
↔ Post
示例。@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
) 上找到我们打算支持的功能列表。
不支持功能的内省警告的解决方法
如果您使用的是关系数据库,并且使用的是上一节中列出的任何上述功能之一
- 创建一个草稿迁移
npx prisma migrate dev --create-only
- 添加在警告中显示的功能的 SQL。
- 将草稿迁移应用到您的数据库
npx prisma migrate dev