跳到主要內容

在 TypeScript 專案中對 PostgreSQL 進行內省

使用 Prisma ORM 內省您的資料庫

為了本指南的目的,我們將使用一個包含三個表的演示 SQL schema

CREATE TABLE "public"."User" (
id SERIAL PRIMARY KEY NOT NULL,
name VARCHAR(255),
email VARCHAR(255) UNIQUE NOT NULL
);

CREATE TABLE "public"."Post" (
id SERIAL PRIMARY KEY NOT NULL,
title VARCHAR(255) NOT NULL,
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
content TEXT,
published BOOLEAN NOT NULL DEFAULT false,
"authorId" INTEGER NOT NULL,
FOREIGN KEY ("authorId") REFERENCES "public"."User"(id)
);

CREATE TABLE "public"."Profile" (
id SERIAL PRIMARY KEY NOT NULL,
bio TEXT,
"userId" INTEGER UNIQUE NOT NULL,
FOREIGN KEY ("userId") REFERENCES "public"."User"(id)
);

注意:某些欄位使用雙引號編寫,以確保 PostgreSQL 使用正確的字母大小寫。如果不使用雙引號,PostgreSQL 會將所有內容都讀取為小寫字元。

展開以查看錶的圖形概覽

User

列名型別主鍵外部索引鍵必需預設值
idSERIAL✔️✔️自動遞增
nameVARCHAR(255)-
emailVARCHAR(255)✔️-

Post

列名型別主鍵外部索引鍵必需預設值
idSERIAL✔️✔️自動遞增
createdAtTIMESTAMP✔️now()
titleVARCHAR(255)✔️-
contentTEXT-
publishedBOOLEAN✔️false
authorIdINTEGER✔️✔️-

Profile

列名型別主鍵外部索引鍵必需預設值
idSERIAL✔️✔️自動遞增
bioTEXT-
userIdINTEGER✔️✔️-

接下來,您將內省您的資料庫。內省的結果將是 Prisma schema 中的一個資料模型

執行以下命令來內省您的資料庫

npx prisma db pull

此命令讀取 .env 中定義的 DATABASE_URL 環境變數並連線到您的資料庫。連線建立後,它會內省資料庫(即讀取資料庫 schema)。然後它將資料庫 schema 從 SQL 轉換為 Prisma schema 中的資料模型。

內省完成後,您的 Prisma schema 已更新

Introspect your database with Prisma ORM

資料模型現在看起來與此類似(請注意,模型上的欄位已重新排序以提高可讀性)

prisma/schema.prisma
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(255)
createdAt DateTime @default(now()) @db.Timestamp(6)
content String?
published Boolean @default(false)
authorId Int
User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction)
}

model Profile {
id Int @id @default(autoincrement())
bio String?
userId Int @unique
User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction)
}

model User {
id Int @id @default(autoincrement())
name String? @db.VarChar(255)
email String @unique @db.VarChar(255)
Post Post[]
Profile Profile?
}

Prisma ORM 的資料模型是您的資料庫 schema 的宣告性表示,並作為生成的 Prisma Client 庫的基礎。您的 Prisma Client 例項將公開根據這些模型量身定製的查詢。

目前,資料模型存在一些小“問題”

  • User 關係欄位採用大寫,因此不符合 Prisma 的命名約定。為了表達更多“語義”,如果此欄位名為 author 以更好地描述 UserPost 之間的關係,那也會很好。
  • User 上的 PostProfile 關係欄位以及 Profile 上的 User 關係欄位都採用大寫。為了遵循 Prisma 的命名約定,這兩個欄位都應該小寫為 postprofileuser
  • 即使小寫後,User 上的 post 欄位仍略有命名錯誤。這是因為它實際上指的是一個帖子的列表——因此更好的名稱應該是複數形式:posts

這些更改對於生成的 Prisma Client API 很重要,在其中使用小寫關係欄位 authorpostsprofileuser 會讓 JavaScript/TypeScript 開發者感覺更自然、更地道。因此,您可以配置您的 Prisma Client API

由於關係欄位虛擬的(即它們不會直接在資料庫中體現),因此您可以在 Prisma schema 中手動重新命名它們,而無需更改資料庫

prisma/schema.prisma
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(255)
createdAt DateTime @default(now()) @db.Timestamp(6)
content String?
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction)
}

model Profile {
id Int @id @default(autoincrement())
bio String?
userId Int @unique
user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction)
}

model User {
id Int @id @default(autoincrement())
name String? @db.VarChar(255)
email String @unique @db.VarChar(255)
posts Post[]
profile Profile?
}

在此示例中,資料庫 schema 確實遵循了 Prisma ORM 模型的命名約定(只有從內省生成的虛擬關係欄位不符合約定,需要調整)。這優化了生成的 Prisma Client API 的人體工程學。

使用自定義模型和欄位名稱

不過,有時您可能希望對 Prisma Client API 中公開的列名和表名進行額外更改。一個常見的例子是將資料庫 schema 中常用的snake_case表示法轉換為對 JavaScript/TypeScript 開發者而言更自然的PascalCasecamelCase表示法。

假設您從內省中獲得了以下基於snake_case表示法的模型

model my_user {
user_id Int @id @default(autoincrement())
first_name String?
last_name String @unique
}

如果您為這個模型生成 Prisma Client API,它將在其 API 中採用snake_case表示法

const user = await prisma.my_user.create({
data: {
first_name: 'Alice',
last_name: 'Smith',
},
})

如果您不想在 Prisma Client API 中使用資料庫中的表名和列名,您可以使用@map@@map 進行配置。

model MyUser {
userId Int @id @default(autoincrement()) @map("user_id")
firstName String? @map("first_name")
lastName String @unique @map("last_name")

@@map("my_user")
}

透過這種方法,您可以隨意命名您的模型及其欄位,並使用 @map(用於欄位名)和 @@map(用於模型名)指向底層表和列。您的 Prisma Client API 現在看起來如下:

const user = await prisma.myUser.create({
data: {
firstName: 'Alice',
lastName: 'Smith',
},
})

配置您的 Prisma Client API 頁面瞭解更多資訊。

© . This site is unofficial and not affiliated with Prisma Data, Inc.