内省
你可以使用 Prisma CLI 内省你的数据库,以便在你的 Prisma Schema 中生成数据模型。生成 Prisma Client 需要数据模型。
当将 Prisma ORM 添加到现有项目时,内省通常用于生成数据模型的初始版本。
然而,它也可以在应用程序中被重复使用。这最常发生在您不使用 Prisma Migrate,而是使用纯 SQL 或其他迁移工具执行模式迁移时。在这种情况下,您还需要重新内省数据库,然后重新生成 Prisma Client,以反映 Prisma Client API 中的模式更改。
内省做什么?
内省有一个主要功能:使用反映当前数据库模式的数据模型填充你的 Prisma Schema。
以下是它在 SQL 数据库上的主要功能概览
- 将数据库中的表映射到 Prisma 模型
- 将数据库中的列映射到 Prisma 模型的字段
- 将数据库中的索引映射到 Prisma Schema 中的索引
- 将数据库约束映射到 Prisma Schema 中的属性或类型修饰符
在 MongoDB 上,主要功能如下
- 将数据库中的集合映射到 Prisma 模型。由于 MongoDB 中的集合没有预定义的结构,Prisma ORM 会对集合中的文档进行抽样,并据此推导出模型结构(即将文档的字段映射到 Prisma 模型的字段)。如果在集合中检测到嵌入类型,这些类型将被映射到 Prisma Schema 中的复合类型。
- 将数据库中的索引映射到 Prisma Schema 中的索引,前提是集合中至少有一个文档包含索引中包含的字段
你可以从各个数据源连接器文档页面了解更多关于 Prisma ORM 如何将数据库中的类型映射到 Prisma Schema 中可用类型的信息
prisma db pull
命令
你可以使用 Prisma CLI 的 prisma db pull
命令来内省你的数据库。请注意,使用此命令需要你在 Prisma Schema datasource
中设置连接 URL。
以下是 prisma db pull
在内部执行步骤的高级概览
- 从 Prisma Schema 的
datasource
配置中读取连接 URL - 打开到数据库的连接
- 内省数据库模式(即读取表、列和其他结构...)
- 将数据库模式转换为 Prisma Schema 数据模型
- 将数据模型写入 Prisma Schema 或更新现有模式
内省工作流程
对于不使用 Prisma Migrate,而是使用纯 SQL 或其他迁移工具的项目,典型的工作流程如下
- 更改数据库模式(例如使用纯 SQL)
- 运行
prisma db pull
更新 Prisma Schema - 运行
prisma generate
更新 Prisma Client - 在你的应用程序中使用更新后的 Prisma Client
请注意,随着应用程序的发展,此过程可以无限次重复。
规则与约定
Prisma ORM 采用了一些约定,用于将数据库模式转换为 Prisma Schema 中的数据模型
模型、字段和枚举名称
字段、模型和枚举名称(标识符)必须以字母开头,并且通常只能包含下划线、字母和数字。你可以在相应的文档页面找到这些标识符的命名规则和约定
标识符的通用规则是它们需要符合此正则表达式
[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 Schema 中不允许重复的模型名称。
字段顺序
内省按照数据库中对应表列的顺序列出模型字段。
属性顺序
内省按照以下顺序添加属性(此顺序与 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 Schema 中定义多对多关系的方式
如果关系表符合 Prisma ORM 的关系表约定,则识别为隐式多对多关系。否则,关系表将在 Prisma Schema 中作为模型渲染(因此使其成为显式多对多关系)。
此主题在关于关系的文档页面上有详细介绍。
消歧关系
如果不需要,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 Schema 的关系型数据库,运行 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 Schema,请将 --force
标志添加到 db pull
命令中
npx prisma db pull --force
用例包括
- 你想从头开始使用底层数据库生成的模式
- 你的模式无效,必须使用
--force
才能使内省成功
仅内省数据库模式的子集
Prisma ORM 尚未正式支持仅内省数据库模式的子集。
但是,你可以通过创建一个新的数据库用户来实现此目的,该用户仅有权访问你想在 Prisma Schema 中表示的表,然后使用该用户执行内省。内省将仅包含新用户有权访问的表。
如果你的目标是从Prisma Client 生成中排除某些模型,你可以在 Prisma Schema 中的模型定义中添加@@ignore
属性。被忽略的模型将从生成的 Prisma Client 中排除。
内省对不支持功能的警告
Prisma Schema Language (PSL) 可以表达 Prisma ORM 支持的目标数据库的大部分数据库功能。然而,Prisma Schema Language 仍需要表达一些特性和功能。
对于这些功能,Prisma CLI 会检测到你在数据库中使用了该功能并返回警告。Prisma CLI 还会在 Prisma Schema 中使用了这些功能的模型和字段中添加注释。警告还会包含一个临时的解决方案建议。
prisma db pull
命令会提示以下不受支持的功能
- 自版本 4.13.0 起
- 自版本 4.14.0 起
- Check Constraints (MySQL + PostgreSQL)
- 排除约束
- MongoDB $jsonSchema
- 自版本 4.16.0 起
你可以在 GitHub 上找到我们计划支持的功能列表(带有 topic:database-functionality
标签)。
不支持功能的内省警告的临时解决方案
如果你正在使用关系型数据库以及上一节中列出的任一功能
- 创建一个草稿迁移
npx prisma migrate dev --create-only
- 添加用于添加警告中提示功能的 SQL。
- 将草稿迁移应用到你的数据库
npx prisma migrate dev